Skip to content

Commit 2c6d717

Browse files
authored
Migrate implementation of json_serializable to null-safety (#841)
Fixes #821
1 parent d33363e commit 2c6d717

File tree

143 files changed

+275
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+275
-438
lines changed

json_annotation/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
## 4.0.1-dev
1+
## 4.0.1
22

33
- Fix a potential error with `checked: true` when `ArgumentError.message` is
44
`null`.
5+
- Updated `JsonSerializable.fromJson` to handle `null` values.
56

67
## 4.0.0
78

json_annotation/lib/src/json_serializable.g.dart

Lines changed: 37 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

json_annotation/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: json_annotation
2-
version: 4.0.1-dev
2+
version: 4.0.1
33
description: >-
44
Classes and helper functions that support JSON code generation via the
55
`json_serializable` package.
@@ -10,4 +10,4 @@ environment:
1010
# When changing JsonSerializable class.
1111
# dev_dependencies:
1212
# build_runner: ^1.0.0
13-
# json_serializable: ^3.1.0
13+
# json_serializable: ^4.0.0

json_serializable/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 5.0.0-dev
2+
3+
- Implementation is now null-safe.
4+
15
## 4.0.3
26

37
- Correctly handle nullable values with `genericArgumentFactories`.

json_serializable/example/example.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// @dart=2.12
6-
75
import 'package:json_annotation/json_annotation.dart';
86

97
part 'example.g.dart';

json_serializable/example/example.g.dart

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

json_serializable/lib/builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Builder jsonSerializable(BuilderOptions options) {
3434
lines.add('There is a problem with "${e.key}".');
3535
}
3636
if (e.message != null) {
37-
lines.add(e.message);
37+
lines.add(e.message!);
3838
} else if (e.innerError != null) {
3939
lines.add(e.innerError.toString());
4040
}

json_serializable/lib/src/decode_helper.dart

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ abstract class DecodeHelper implements HelperCore {
2525
Map<String, FieldElement> accessibleFields,
2626
Map<String, String> unavailableReasons,
2727
) {
28-
assert(config.createFactory);
28+
assert(config.createFactory!);
2929
final buffer = StringBuffer();
3030

31-
final mapType = config.anyMap ? 'Map' : 'Map<String, dynamic>';
31+
final mapType = config.anyMap! ? 'Map' : 'Map<String, dynamic>';
3232
buffer.write('$targetClassReference '
3333
'${prefix}FromJson${genericClassArgumentsImpl(true)}'
3434
'($mapType json');
3535

36-
if (config.genericArgumentFactories) {
36+
if (config.genericArgumentFactories!) {
3737
for (var arg in element.typeParameters) {
3838
final helperName = fromJsonForType(
3939
arg.instantiate(nullabilitySuffix: NullabilitySuffix.none),
@@ -49,8 +49,8 @@ abstract class DecodeHelper implements HelperCore {
4949
buffer.write(') {\n');
5050

5151
String deserializeFun(String paramOrFieldName,
52-
{ParameterElement ctorParam}) =>
53-
_deserializeForField(accessibleFields[paramOrFieldName],
52+
{ParameterElement? ctorParam}) =>
53+
_deserializeForField(accessibleFields[paramOrFieldName]!,
5454
ctorParam: ctorParam);
5555

5656
final data = _writeConstructorInvocation(
@@ -72,7 +72,7 @@ abstract class DecodeHelper implements HelperCore {
7272
final checks = _checkKeys(accessibleFields.values
7373
.where((fe) => data.usedCtorParamsAndFields.contains(fe.name)));
7474

75-
if (config.checked) {
75+
if (config.checked!) {
7676
final classLiteral = escapeDartString(element.name);
7777

7878
buffer..write('''
@@ -84,12 +84,12 @@ abstract class DecodeHelper implements HelperCore {
8484

8585
for (final field in data.fieldsToSet) {
8686
buffer.writeln();
87-
final safeName = safeNameAccess(accessibleFields[field]);
87+
final safeName = safeNameAccess(accessibleFields[field]!);
8888
buffer
8989
..write('''
9090
\$checkedConvert(json, $safeName, (v) => ''')
9191
..write('val.$field = ')
92-
..write(_deserializeForField(accessibleFields[field],
92+
..write(_deserializeForField(accessibleFields[field]!,
9393
checkedProperty: true))
9494
..write(');');
9595
}
@@ -98,7 +98,7 @@ abstract class DecodeHelper implements HelperCore {
9898
}''');
9999

100100
final fieldKeyMap = Map.fromEntries(data.usedCtorParamsAndFields
101-
.map((k) => MapEntry(k, nameAccess(accessibleFields[k])))
101+
.map((k) => MapEntry(k, nameAccess(accessibleFields[k]!)))
102102
.where((me) => me.key != me.value));
103103

104104
String fieldKeyMapArg;
@@ -131,22 +131,22 @@ abstract class DecodeHelper implements HelperCore {
131131
String constantList(Iterable<FieldElement> things) =>
132132
'const ${jsonLiteralAsDart(things.map(nameAccess).toList())}';
133133

134-
if (config.disallowUnrecognizedKeys) {
134+
if (config.disallowUnrecognizedKeys!) {
135135
final allowKeysLiteral = constantList(accessibleFields);
136136

137137
args.add('allowedKeys: $allowKeysLiteral');
138138
}
139139

140140
final requiredKeys =
141-
accessibleFields.where((fe) => jsonKeyFor(fe).required).toList();
141+
accessibleFields.where((fe) => jsonKeyFor(fe).required!).toList();
142142
if (requiredKeys.isNotEmpty) {
143143
final requiredKeyLiteral = constantList(requiredKeys);
144144

145145
args.add('requiredKeys: $requiredKeyLiteral');
146146
}
147147

148148
final disallowNullKeys = accessibleFields
149-
.where((fe) => jsonKeyFor(fe).disallowNullValue)
149+
.where((fe) => jsonKeyFor(fe).disallowNullValue!)
150150
.toList();
151151
if (disallowNullKeys.isNotEmpty) {
152152
final disallowNullKeyLiteral = constantList(disallowNullKeys);
@@ -163,18 +163,17 @@ abstract class DecodeHelper implements HelperCore {
163163

164164
String _deserializeForField(
165165
FieldElement field, {
166-
ParameterElement ctorParam,
167-
bool checkedProperty,
166+
ParameterElement? ctorParam,
167+
bool checkedProperty = false,
168168
}) {
169-
checkedProperty ??= false;
170169
final jsonKeyName = safeNameAccess(field);
171170
final targetType = ctorParam?.type ?? field.type;
172171
final contextHelper = getHelperContext(field);
173172
final defaultProvided = jsonKeyFor(field).defaultValue != null;
174173

175174
String value;
176175
try {
177-
if (config.checked) {
176+
if (config.checked!) {
178177
value = contextHelper
179178
.deserialize(
180179
targetType,
@@ -205,7 +204,7 @@ abstract class DecodeHelper implements HelperCore {
205204
final jsonKey = jsonKeyFor(field);
206205
final defaultValue = jsonKey.defaultValue;
207206
if (defaultValue != null) {
208-
if (jsonKey.disallowNullValue && jsonKey.required) {
207+
if (jsonKey.disallowNullValue! && jsonKey.required!) {
209208
log.warning('The `defaultValue` on field `${field.name}` will have no '
210209
'effect because both `disallowNullValue` and `required` are set to '
211210
'`true`.');

json_serializable/lib/src/encoder_helper.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ abstract class EncodeHelper implements HelperCore {
1717
String _fieldAccess(FieldElement field) => '$_toJsonParamName.${field.name}';
1818

1919
Iterable<String> createToJson(Set<FieldElement> accessibleFields) sync* {
20-
assert(config.createToJson);
20+
assert(config.createToJson!);
2121

2222
final buffer = StringBuffer();
2323

2424
final functionName = '${prefix}ToJson${genericClassArgumentsImpl(true)}';
2525
buffer.write('Map<String, dynamic> '
2626
'$functionName($targetClassReference $_toJsonParamName');
2727

28-
if (config.genericArgumentFactories) {
28+
if (config.genericArgumentFactories!) {
2929
for (var arg in element.typeParameters) {
3030
final helperName = toJsonForType(
3131
arg.instantiate(nullabilitySuffix: NullabilitySuffix.none),
@@ -140,7 +140,7 @@ abstract class EncodeHelper implements HelperCore {
140140
bool _writeJsonValueNaive(FieldElement field) {
141141
final jsonKey = jsonKeyFor(field);
142142

143-
return jsonKey.includeIfNull ||
143+
return jsonKey.includeIfNull! ||
144144
(!field.type.isNullableType && !_fieldHasCustomEncoder(field));
145145
}
146146

json_serializable/lib/src/field_helpers.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ class _FieldSet implements Comparable<_FieldSet> {
1717
_FieldSet._(this.field, this.sortField)
1818
: assert(field.name == sortField.name);
1919

20-
factory _FieldSet(FieldElement classField, FieldElement superField) {
20+
factory _FieldSet(FieldElement? classField, FieldElement? superField) {
2121
// At least one of these will != null, perhaps both.
22-
final fields = [classField, superField].where((fe) => fe != null).toList();
22+
final fields = [classField, superField].whereType<FieldElement>().toList();
2323

2424
// Prefer the class field over the inherited field when sorting.
2525
final sortField = fields.first;
@@ -58,9 +58,9 @@ class _FieldSet implements Comparable<_FieldSet> {
5858
/// Returns the offset of given field/property in its source file – with a
5959
/// preference for the getter if it's defined.
6060
int _offsetFor(FieldElement e) {
61-
if (e.getter != null && e.getter.nameOffset != e.nameOffset) {
61+
if (e.getter != null && e.getter!.nameOffset != e.nameOffset) {
6262
assert(e.nameOffset == -1);
63-
return e.getter.nameOffset;
63+
return e.getter!.nameOffset;
6464
}
6565
return e.nameOffset;
6666
}

0 commit comments

Comments
 (0)