diff --git a/_test_yaml/test/src/build_config.g.dart b/_test_yaml/test/src/build_config.g.dart index 78bb619b..e453d996 100644 --- a/_test_yaml/test/src/build_config.g.dart +++ b/_test_yaml/test/src/build_config.g.dart @@ -119,20 +119,17 @@ Builder _$BuilderFromJson(Map json) => $checkedCreate( ); Map _$BuilderToJson(Builder instance) => { - if (instance.target case final value?) 'target': value, - if (instance.import case final value?) 'import': value, - if (instance.isOptional case final value?) 'is_optional': value, - if (instance.configLocation?.toString() case final value?) - 'configLocation': value, - if (_$AutoApplyEnumMap[instance.autoApply] case final value?) - 'auto_apply': value, - if (_$BuildToEnumMap[instance.buildTo] case final value?) 'build_to': value, - if (_$AutoApplyEnumMap[instance.defaultEnumTest] case final value?) - 'defaultEnumTest': value, + 'target': ?instance.target, + 'import': ?instance.import, + 'is_optional': ?instance.isOptional, + 'configLocation': ?instance.configLocation?.toString(), + 'auto_apply': ?_$AutoApplyEnumMap[instance.autoApply], + 'build_to': ?_$BuildToEnumMap[instance.buildTo], + 'defaultEnumTest': ?_$AutoApplyEnumMap[instance.defaultEnumTest], 'builder_factories': instance.builderFactories, - if (instance.appliesBuilders case final value?) 'applies_builders': value, - if (instance.requiredInputs case final value?) 'required_inputs': value, - if (instance.buildExtensions case final value?) 'build_extensions': value, + 'applies_builders': ?instance.appliesBuilders, + 'required_inputs': ?instance.requiredInputs, + 'build_extensions': ?instance.buildExtensions, }; const _$BuildToEnumMap = {BuildTo.cache: 'cache', BuildTo.source: 'source'}; diff --git a/analysis_options.yaml b/analysis_options.yaml index f87c95a7..24ad09c2 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -29,4 +29,5 @@ linter: - unnecessary_breaks - unnecessary_ignore - use_full_hex_values_for_flutter_colors + - use_null_aware_elements - use_string_buffers diff --git a/example/lib/example.g.dart b/example/lib/example.g.dart index c35c960a..6c1d3cb0 100644 --- a/example/lib/example.g.dart +++ b/example/lib/example.g.dart @@ -21,7 +21,7 @@ Person _$PersonFromJson(Map json) => Person( Map _$PersonToJson(Person instance) => { 'firstName': instance.firstName, - if (instance.middleName case final value?) 'middleName': value, + 'middleName': ?instance.middleName, 'lastName': instance.lastName, 'date-of-birth': instance.dateOfBirth.toIso8601String(), 'last-order': instance.lastOrder?.toIso8601String(), @@ -41,13 +41,12 @@ Order _$OrderFromJson(Map json) => ); Map _$OrderToJson(Order instance) => { - if (instance.count case final value?) 'count': value, - if (instance.itemNumber case final value?) 'itemNumber': value, - if (instance.isRushed case final value?) 'isRushed': value, - if (instance.item case final value?) 'item': value, - if (Order._durationToMilliseconds(instance.prepTime) case final value?) - 'prep-time': value, - if (Order._dateTimeToEpochUs(instance.date) case final value?) 'date': value, + 'count': ?instance.count, + 'itemNumber': ?instance.itemNumber, + 'isRushed': ?instance.isRushed, + 'item': ?instance.item, + 'prep-time': ?Order._durationToMilliseconds(instance.prepTime), + 'date': ?Order._dateTimeToEpochUs(instance.date), }; Item _$ItemFromJson(Map json) => Item() diff --git a/json_serializable/CHANGELOG.md b/json_serializable/CHANGELOG.md index 4d1b7a63..43ab453d 100644 --- a/json_serializable/CHANGELOG.md +++ b/json_serializable/CHANGELOG.md @@ -1,6 +1,7 @@ ## 6.9.6-wip - Move `package:collection` to a dev dependency. +- Use new `null-aware element` feature in generated code. - Require Dart 3.8 ## 6.9.5 diff --git a/json_serializable/lib/src/constants.dart b/json_serializable/lib/src/constants.dart index 70e85216..f10fd806 100644 --- a/json_serializable/lib/src/constants.dart +++ b/json_serializable/lib/src/constants.dart @@ -14,6 +14,6 @@ const converterOrKeyInstructions = r''' https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html'''; -/// This package generates code that uses case statements, which were introduced -/// in Dart 3.0. -const supportedLanguageConstraint = '^3.0.0'; +/// This package generates code that uses null-aware elements, which were +/// introduced in Dart 3.8. +const supportedLanguageConstraint = '^3.8.0'; diff --git a/json_serializable/lib/src/encoder_helper.dart b/json_serializable/lib/src/encoder_helper.dart index dc7e8a9e..7effcd05 100644 --- a/json_serializable/lib/src/encoder_helper.dart +++ b/json_serializable/lib/src/encoder_helper.dart @@ -6,7 +6,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:source_helper/source_helper.dart'; -import 'constants.dart'; import 'enum_utils.dart'; import 'helper_core.dart'; import 'type_helpers/generic_factory_helper.dart'; @@ -109,10 +108,9 @@ mixin EncodeHelper implements HelperCore { final keyExpression = safeNameAccess(field); final valueExpression = _serializeField(field, access); - final keyValuePair = _canWriteJsonWithoutNullCheck(field) - ? '$keyExpression: $valueExpression' - : 'if ($valueExpression case final $generatedLocalVarName?) ' - '$keyExpression: $generatedLocalVarName'; + final maybeQuestion = _canWriteJsonWithoutNullCheck(field) ? '' : '?'; + + final keyValuePair = '$keyExpression: $maybeQuestion$valueExpression'; return ' $keyValuePair,\n'; }), ) diff --git a/json_serializable/test/annotation_version_test.dart b/json_serializable/test/annotation_version_test.dart index 7084abd2..b15d8998 100644 --- a/json_serializable/test/annotation_version_test.dart +++ b/json_serializable/test/annotation_version_test.dart @@ -32,7 +32,7 @@ void main() { group('language version', () { test('is less than required', () async { - const sdkLowerBound = '2.12.0'; + const sdkLowerBound = '3.7.0'; await _structurePackage( environment: const {'sdk': '^$sdkLowerBound'}, dependencies: {'json_annotation': _annotationLowerBound}, diff --git a/json_serializable/test/integration/converter_examples.g.dart b/json_serializable/test/integration/converter_examples.g.dart index d91d76d9..7315b4a3 100644 --- a/json_serializable/test/integration/converter_examples.g.dart +++ b/json_serializable/test/integration/converter_examples.g.dart @@ -33,20 +33,15 @@ Map _$Issue1202RegressionClassToJson( ), 'notNullableValueWithConverter': const _Issue1202RegressionNotNullConverter() .toJson(instance.notNullableValueWithConverter), - if (_$Issue1202RegressionEnumEnumMap[instance.value] case final value?) - 'value': value, - if (instance.normalNullableValue case final value?) - 'normalNullableValue': value, - if (const _Issue1202RegressionConverter().toJson( + 'value': ?_$Issue1202RegressionEnumEnumMap[instance.value], + 'normalNullableValue': ?instance.normalNullableValue, + 'notNullableValueWithNullableConverter': + ?const _Issue1202RegressionConverter().toJson( instance.notNullableValueWithNullableConverter, - ) - case final value?) - 'notNullableValueWithNullableConverter': value, - if (Issue1202RegressionClass._toJsonNullable( - instance.valueWithNullableFunctions, - ) - case final value?) - 'valueWithNullableFunctions': value, + ), + 'valueWithNullableFunctions': ?Issue1202RegressionClass._toJsonNullable( + instance.valueWithNullableFunctions, + ), }; const _$Issue1202RegressionEnumEnumMap = { @@ -64,12 +59,10 @@ Regression1229 _$Regression1229FromJson(Map json) => Map _$Regression1229ToJson(Regression1229 instance) => { - if (_$JsonConverterToJson( - instance.date, - const DateTimeConverter().toJson, - ) - case final value?) - 'date': value, + 'date': ?_$JsonConverterToJson( + instance.date, + const DateTimeConverter().toJson, + ), }; Value? _$JsonConverterFromJson( diff --git a/json_serializable/test/integration/create_per_field_to_json_example.g.dart b/json_serializable/test/integration/create_per_field_to_json_example.g.dart index 14d7d9f0..f77139ee 100644 --- a/json_serializable/test/integration/create_per_field_to_json_example.g.dart +++ b/json_serializable/test/integration/create_per_field_to_json_example.g.dart @@ -49,8 +49,7 @@ Map _$ModelToJson(Model instance) => { 'enumValue': _$EnumValueEnumMap[instance.enumValue], 'nested': instance.nested?.toJson(), 'nestedGeneric': instance.nestedGeneric?.toJson((value) => value), - if (instance.nestedExcludeIfNull?.toJson() case final value?) - 'nestedExcludeIfNull': value, + 'nestedExcludeIfNull': ?instance.nestedExcludeIfNull?.toJson(), }; const _$EnumValueEnumMap = {EnumValue.first: '1', EnumValue.second: 'second'}; diff --git a/json_serializable/test/integration/json_enum_example.g.dart b/json_serializable/test/integration/json_enum_example.g.dart index 3558c1a7..0cbe2616 100644 --- a/json_serializable/test/integration/json_enum_example.g.dart +++ b/json_serializable/test/integration/json_enum_example.g.dart @@ -62,8 +62,7 @@ Issue1226Regression _$Issue1226RegressionFromJson(Map json) => Map _$Issue1226RegressionToJson( Issue1226Regression instance, ) => { - if (_$Issue1145RegressionEnumEnumMap[instance.durationType] case final value?) - 'durationType': value, + 'durationType': ?_$Issue1145RegressionEnumEnumMap[instance.durationType], }; const _$StandAloneEnumEnumMap = { diff --git a/json_serializable/test/integration/json_test_example.g.dart b/json_serializable/test/integration/json_test_example.g.dart index cd32ac92..1f1b456e 100644 --- a/json_serializable/test/integration/json_test_example.g.dart +++ b/json_serializable/test/integration/json_test_example.g.dart @@ -94,7 +94,7 @@ Order _$OrderFromJson(Map json) { } Map _$OrderToJson(Order instance) => { - if (instance.count case final value?) 'count': value, + 'count': ?instance.count, 'isRushed': instance.isRushed, 'duration': instance.duration?.inMicroseconds, 'category': _$CategoryEnumMap[instance.category], @@ -125,7 +125,7 @@ Item _$ItemFromJson(Map json) => Map _$ItemToJson(Item instance) => { 'price': instance.price, - if (instance.itemNumber case final value?) 'item-number': value, + 'item-number': ?instance.itemNumber, 'saleDates': instance.saleDates?.map((e) => e.toIso8601String()).toList(), 'rates': instance.rates, 'geoPoint': _toJsonGeoPoint(instance.geoPoint), diff --git a/json_serializable/test/integration/json_test_example.g_any_map.g.dart b/json_serializable/test/integration/json_test_example.g_any_map.g.dart index f277591b..f25c7971 100644 --- a/json_serializable/test/integration/json_test_example.g_any_map.g.dart +++ b/json_serializable/test/integration/json_test_example.g_any_map.g.dart @@ -96,7 +96,7 @@ Order _$OrderFromJson(Map json) { } Map _$OrderToJson(Order instance) => { - if (instance.count case final value?) 'count': value, + 'count': ?instance.count, 'isRushed': instance.isRushed, 'duration': instance.duration?.inMicroseconds, 'category': _$CategoryEnumMap[instance.category], @@ -126,7 +126,7 @@ Item _$ItemFromJson(Map json) => Item((json['price'] as num?)?.toInt()) Map _$ItemToJson(Item instance) => { 'price': instance.price, - if (instance.itemNumber case final value?) 'item-number': value, + 'item-number': ?instance.itemNumber, 'saleDates': instance.saleDates?.map((e) => e.toIso8601String()).toList(), 'rates': instance.rates, 'geoPoint': _toJsonGeoPoint(instance.geoPoint), diff --git a/json_serializable/test/kitchen_sink/kitchen_sink.g_exclude_null.g.dart b/json_serializable/test/kitchen_sink/kitchen_sink.g_exclude_null.g.dart index 3ea352ae..57ca8248 100644 --- a/json_serializable/test/kitchen_sink/kitchen_sink.g_exclude_null.g.dart +++ b/json_serializable/test/kitchen_sink/kitchen_sink.g_exclude_null.g.dart @@ -118,10 +118,10 @@ KitchenSink _$KitchenSinkFromJson(Map json) => Map _$KitchenSinkToJson( KitchenSink instance, ) => { - if (instance.ctorValidatedNo42 case final value?) 'no-42': value, - if (instance.dateTime?.toIso8601String() case final value?) 'dateTime': value, - if (instance.bigInt?.toString() case final value?) 'bigInt': value, - if (instance.iterable?.toList() case final value?) 'iterable': value, + 'no-42': ?instance.ctorValidatedNo42, + 'dateTime': ?instance.dateTime?.toIso8601String(), + 'bigInt': ?instance.bigInt?.toString(), + 'iterable': ?instance.iterable?.toList(), 'dynamicIterable': instance.dynamicIterable.toList(), 'objectIterable': instance.objectIterable.toList(), 'intIterable': instance.intIterable.toList(), @@ -166,21 +166,18 @@ Map _$KitchenSinkToJson( ) .toList(), 'val': instance.val, - if (instance.writeNotNull case final value?) 'writeNotNull': value, - if (instance.string case final value?) r'$string': value, + 'writeNotNull': ?instance.writeNotNull, + r'$string': ?instance.string, 'simpleObject': instance.simpleObject, 'strictKeysObject': instance.strictKeysObject, - if (instance.validatedPropertyNo42 case final value?) - 'validatedPropertyNo42': value, - if (instance.recordField == null - ? null - : { - r'$1': instance.recordField!.$1, - r'$2': instance.recordField!.$2, - 'truth': instance.recordField!.truth, - } - case final value?) - 'recordField': value, + 'validatedPropertyNo42': ?instance.validatedPropertyNo42, + 'recordField': ?instance.recordField == null + ? null + : { + r'$1': instance.recordField!.$1, + r'$2': instance.recordField!.$2, + 'truth': instance.recordField!.truth, + }, }; $Rec? _$recordConvertNullable<$Rec>( @@ -240,9 +237,7 @@ JsonConverterTestClass _$JsonConverterTestClassFromJson( Map _$JsonConverterTestClassToJson( JsonConverterTestClass instance, ) => { - if (const DurationMillisecondConverter().toJson(instance.duration) - case final value?) - 'duration': value, + 'duration': ?const DurationMillisecondConverter().toJson(instance.duration), 'durationList': instance.durationList .map(const DurationMillisecondConverter().toJson) .toList(), @@ -250,12 +245,10 @@ Map _$JsonConverterTestClassToJson( 'bigIntMap': instance.bigIntMap.map( (k, e) => MapEntry(k, const BigIntStringConverter().toJson(e)), ), - if (_$JsonConverterToJson( - instance.nullableBigInt, - const BigIntStringConverter().toJson, - ) - case final value?) - 'nullableBigInt': value, + 'nullableBigInt': ?_$JsonConverterToJson( + instance.nullableBigInt, + const BigIntStringConverter().toJson, + ), 'nullableBigIntMap': instance.nullableBigIntMap.map( (k, e) => MapEntry( k, @@ -265,23 +258,16 @@ Map _$JsonConverterTestClassToJson( ), ), ), - if (TrivialNumberConverter.instance.toJson(instance.numberSilly) - case final value?) - 'numberSilly': value, + 'numberSilly': ?TrivialNumberConverter.instance.toJson(instance.numberSilly), 'numberSillySet': instance.numberSillySet .map(TrivialNumberConverter.instance.toJson) .toList(), - if (const EpochDateTimeConverter().toJson(instance.dateTime) - case final value?) - 'dateTime': value, - if (trivialStringConverter.toJson(instance.trivialString) case final value?) - 'trivialString': value, - if (_$JsonConverterToJson( - instance.nullableNumberSilly, - TrivialNumberConverter.instance.toJson, - ) - case final value?) - 'nullableNumberSilly': value, + 'dateTime': ?const EpochDateTimeConverter().toJson(instance.dateTime), + 'trivialString': ?trivialStringConverter.toJson(instance.trivialString), + 'nullableNumberSilly': ?_$JsonConverterToJson( + instance.nullableNumberSilly, + TrivialNumberConverter.instance.toJson, + ), 'nullableNumberSillySet': instance.nullableNumberSillySet .map( (e) => _$JsonConverterToJson( diff --git a/json_serializable/test/src/_json_serializable_test_input.dart b/json_serializable/test/src/_json_serializable_test_input.dart index c7fbd508..4db90e56 100644 --- a/json_serializable/test/src/_json_serializable_test_input.dart +++ b/json_serializable/test/src/_json_serializable_test_input.dart @@ -199,10 +199,7 @@ class NoDeserializeBadKey { @ShouldGenerate(r''' Map _$IncludeIfNullOverrideToJson( IncludeIfNullOverride instance, -) => { - 'number': instance.number, - if (instance.str case final value?) 'str': value, -}; +) => {'number': instance.number, 'str': ?instance.str}; ''') @JsonSerializable(createFactory: false, includeIfNull: false) class IncludeIfNullOverride { diff --git a/json_serializable/test/src/inheritance_test_input.dart b/json_serializable/test/src/inheritance_test_input.dart index 76caaed2..0aac74d8 100644 --- a/json_serializable/test/src/inheritance_test_input.dart +++ b/json_serializable/test/src/inheritance_test_input.dart @@ -13,8 +13,7 @@ SubType _$SubTypeFromJson(Map json) => Map _$SubTypeToJson(SubType instance) => { 'super-final-field': instance.superFinalField, - if (instance.superReadWriteField case final value?) - 'superReadWriteField': value, + 'superReadWriteField': ?instance.superReadWriteField, 'subTypeViaCtor': instance.subTypeViaCtor, 'subTypeReadWrite': instance.subTypeReadWrite, }; @@ -51,8 +50,7 @@ Map _$SubTypeWithAnnotatedFieldOverrideExtendsToJson( SubTypeWithAnnotatedFieldOverrideExtends instance, ) => { 'super-final-field': instance.superFinalField, - if (instance.superReadWriteField case final value?) - 'superReadWriteField': value, + 'superReadWriteField': ?instance.superReadWriteField, 'priceHalf': instance.priceHalf, }; ''') diff --git a/json_serializable/test/src/to_from_json_test_input.dart b/json_serializable/test/src/to_from_json_test_input.dart index d93db418..f811d6a3 100644 --- a/json_serializable/test/src/to_from_json_test_input.dart +++ b/json_serializable/test/src/to_from_json_test_input.dart @@ -166,9 +166,7 @@ String? _toStringNullOnEmpty(String input) => input.isEmpty ? null : input; @ShouldGenerate(r''' Map _$ToJsonNullableFalseIncludeIfNullFalseToJson( ToJsonNullableFalseIncludeIfNullFalse instance, -) => { - if (_toStringNullOnEmpty(instance.field) case final value?) 'field': value, -}; +) => {'field': ?_toStringNullOnEmpty(instance.field)}; ''') @JsonSerializable(createFactory: false) class ToJsonNullableFalseIncludeIfNullFalse {