Skip to content

Commit 56b6e5b

Browse files
cedvdbCommit Queue
authored andcommitted
Json codable no type assumption in custom fromJson
Closes #59581 GitOrigin-RevId: 8137077 Change-Id: I263a189a6ec181fa8a6e28d77efe20d0cec0629b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/396629 Reviewed-by: Jake Macdonald <[email protected]> Commit-Queue: Jake Macdonald <[email protected]>
1 parent e013a4c commit 56b6e5b

File tree

4 files changed

+147
-5
lines changed

4 files changed

+147
-5
lines changed

pkg/json/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.20.4
2+
3+
- Allow custom `fromJson` to have an arbitrary parameter type.
4+
15
# 0.20.3
26

37
- Add support for DateTime, serializing it to an ISO-8601 String.

pkg/json/lib/json.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,16 +394,16 @@ mixin _FromJson on _Shared {
394394
// Otherwise, check if `classDecl` has a `fromJson` constructor.
395395
final constructors = await builder.constructorsOf(classDecl);
396396
final fromJson = constructors
397-
.firstWhereOrNull((c) => c.identifier.name == 'fromJson')
398-
?.identifier;
397+
.firstWhereOrNull((c) => c.identifier.name == 'fromJson');
398+
399399
if (fromJson != null) {
400400
return RawCode.fromParts([
401401
if (nullCheck != null) nullCheck,
402-
fromJson,
402+
fromJson.identifier,
403403
'(',
404404
jsonReference,
405405
' as ',
406-
introspectionData.jsonMapCode,
406+
fromJson.positionalParameters.first.type.code,
407407
')',
408408
]);
409409
}

pkg/json/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: >
55
`toJson` encoding method.
66
77
repository: https://github.com/dart-lang/sdk/tree/main/pkg/json
8-
version: 0.20.3
8+
version: 0.20.4
99
environment:
1010
sdk: ^3.6.0-edge
1111
dependencies:

pkg/json/test/json_codable_test.dart

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ void main() {
2626
'mapOfSerializableField': {
2727
'c': {'x': 3}
2828
},
29+
'customStringSerializationField': 'hi',
30+
'customNullableStringSerialization': null,
31+
'customMapSerializationField': {
32+
'z': 'zzz',
33+
}
2934
};
3035

3136
var a = A.fromJson(json);
@@ -38,6 +43,11 @@ void main() {
3843
expect(a.listOfSerializableField.single.x, 1);
3944
expect(a.setOfSerializableField.single.x, 2);
4045
expect(a.mapOfSerializableField['c']!.x, 3);
46+
expect(a.customStringSerializationField, CustomStringSerialization('hi'));
47+
expect(a.customNullableStringSerialization,
48+
equals(CustomNullableStringSerialization(null)));
49+
expect(
50+
a.customMapSerializationField, CustomMapSerialization({'z': 'zzz'}));
4151

4252
expect(a.toJson(), equals(json));
4353
});
@@ -59,6 +69,8 @@ void main() {
5969
'nullableMapOfSerializableField': {
6070
'd': {'x': 3},
6171
},
72+
'nullableCustomStringSerializationField': 'hi',
73+
'nullableCustomMapSerializationField': {'z': 'zzz'},
6274
};
6375

6476
var b = B.fromJson(json);
@@ -72,6 +84,10 @@ void main() {
7284
expect(b.nullableListOfSerializableField!.single.x, 1);
7385
expect(b.nullableSetOfSerializableField!.single.x, 2);
7486
expect(b.nullableMapOfSerializableField!['d']!.x, 3);
87+
expect(b.nullableCustomStringSerializationField,
88+
CustomStringSerialization('hi'));
89+
expect(b.nullableCustomMapSerializationField,
90+
CustomMapSerialization({'z': 'zzz'}));
7591

7692
expect(b.toJson(), equals(json));
7793
});
@@ -87,6 +103,8 @@ void main() {
87103
'nullableListOfSerializableField': null,
88104
'nullableSetOfSerializableField': null,
89105
'nullableMapOfSerializableField': null,
106+
'nullableCustomStringSerializationField': null,
107+
'nullableCustomMapSerializationField': null,
90108
});
91109
expect(b.nullableBoolField, null);
92110
expect(b.nullableStringField, null);
@@ -97,6 +115,8 @@ void main() {
97115
expect(b.nullableListOfSerializableField, null);
98116
expect(b.nullableMapOfSerializableField, null);
99117
expect(b.nullableSetOfSerializableField, null);
118+
expect(b.nullableCustomStringSerializationField, null);
119+
expect(b.nullableCustomMapSerializationField, null);
100120

101121
expect(b.toJson(), isEmpty);
102122
});
@@ -112,6 +132,8 @@ void main() {
112132
expect(b.nullableListOfSerializableField, null);
113133
expect(b.nullableMapOfSerializableField, null);
114134
expect(b.nullableSetOfSerializableField, null);
135+
expect(b.nullableCustomStringSerializationField, null);
136+
expect(b.nullableCustomMapSerializationField, null);
115137

116138
expect(b.toJson(), isEmpty);
117139
});
@@ -140,6 +162,11 @@ void main() {
140162
null,
141163
{'a': 1, 'b': null},
142164
],
165+
'listOfCustomStringSerializables': [null, 'hi'],
166+
'listOfCustomMapSerializables': [
167+
null,
168+
{'z': 'zzz'},
169+
],
143170
'setOfNullableDates': [
144171
null,
145172
'2024-11-12T03:42:29.108308',
@@ -159,6 +186,11 @@ void main() {
159186
'b': null,
160187
},
161188
],
189+
'setOfCustomStringSerializables': [null, 'hi'],
190+
'setOfCustomMapSerializables': [
191+
null,
192+
{'z': 'zzz'}
193+
],
162194
'mapOfNullableDates': {
163195
'a': '2024-11-13T03:42:29.108308',
164196
'b': null,
@@ -175,6 +207,14 @@ void main() {
175207
'a': [null, 3],
176208
'b': null,
177209
},
210+
'mapOfCustomStringSerializables': {
211+
'a': null,
212+
'b': 'hi',
213+
},
214+
'mapOfCustomMapSerializables': {
215+
'a': null,
216+
'b': {'z': 'zzz'},
217+
},
178218
};
179219

180220
var e = E.fromJson(json);
@@ -189,6 +229,13 @@ void main() {
189229
null,
190230
{'a': 1, 'b': null},
191231
]));
232+
expect(e.listOfCustomStringSerializables.first, null);
233+
expect(e.listOfCustomStringSerializables[1],
234+
CustomStringSerialization('hi'));
235+
expect(e.listOfCustomMapSerializables.first, null);
236+
expect(e.listOfCustomMapSerializables[1],
237+
CustomMapSerialization({'z': 'zzz'}));
238+
192239
expect(e.setOfNullableDates,
193240
equals([null, DateTime.parse('2024-11-12T03:42:29.108308')]));
194241
expect(e.setOfNullableInts, equals({null, 2}));
@@ -203,6 +250,13 @@ void main() {
203250
'b': null,
204251
},
205252
}));
253+
expect(e.setOfCustomStringSerializables.first, null);
254+
expect(e.setOfCustomStringSerializables.toList()[1],
255+
CustomStringSerialization('hi'));
256+
expect(e.setOfCustomMapSerializables.first, null);
257+
expect(e.setOfCustomMapSerializables.toList()[1],
258+
CustomMapSerialization({'z': 'zzz'}));
259+
206260
expect(
207261
e.mapOfNullableDates,
208262
equals({
@@ -222,6 +276,12 @@ void main() {
222276
'a': {null, 3},
223277
'b': null,
224278
});
279+
expect(e.mapOfCustomStringSerializables['a'], null);
280+
expect(e.mapOfCustomStringSerializables['b'],
281+
CustomStringSerialization('hi'));
282+
expect(e.mapOfCustomMapSerializables['a'], null);
283+
expect(e.mapOfCustomMapSerializables['b'],
284+
CustomMapSerialization({'z': 'zzz'}));
225285

226286
expect(e.toJson(), equals(json));
227287
});
@@ -257,6 +317,12 @@ class A {
257317
final Set<C> setOfSerializableField;
258318

259319
final Map<String, C> mapOfSerializableField;
320+
321+
final CustomStringSerialization customStringSerializationField;
322+
323+
final CustomMapSerialization customMapSerializationField;
324+
325+
final CustomNullableStringSerialization customNullableStringSerialization;
260326
}
261327

262328
@JsonCodable()
@@ -278,6 +344,10 @@ class B {
278344
final Set<C>? nullableSetOfSerializableField;
279345

280346
final Map<String, C>? nullableMapOfSerializableField;
347+
348+
final CustomStringSerialization? nullableCustomStringSerializationField;
349+
350+
final CustomMapSerialization? nullableCustomMapSerializationField;
281351
}
282352

283353
@JsonCodable()
@@ -300,6 +370,10 @@ class E {
300370

301371
final List<Map<String, int?>?> listOfNullableMapsOfNullableInts;
302372

373+
final List<CustomStringSerialization?> listOfCustomStringSerializables;
374+
375+
final List<CustomMapSerialization?> listOfCustomMapSerializables;
376+
303377
final Set<DateTime?> setOfNullableDates;
304378

305379
final Set<int?> setOfNullableInts;
@@ -308,16 +382,80 @@ class E {
308382

309383
final Set<Map<String, int?>?> setOfNullableMapsOfNullableInts;
310384

385+
final Set<CustomStringSerialization?> setOfCustomStringSerializables;
386+
387+
final Set<CustomMapSerialization?> setOfCustomMapSerializables;
388+
311389
final Map<String, DateTime?> mapOfNullableDates;
312390

313391
final Map<String, int?> mapOfNullableInts;
314392

315393
final Map<String, C?> mapOfNullableSerializables;
316394

317395
final Map<String, Set<int?>?> mapOfNullableSetsOfNullableInts;
396+
397+
final Map<String, CustomStringSerialization?> mapOfCustomStringSerializables;
398+
399+
final Map<String, CustomMapSerialization?> mapOfCustomMapSerializables;
318400
}
319401

320402
@JsonCodable()
321403
class F {
322404
final int fieldWithDollarSign$;
323405
}
406+
407+
class CustomStringSerialization {
408+
final String a;
409+
410+
CustomStringSerialization(this.a);
411+
412+
String toJson() => a;
413+
414+
factory CustomStringSerialization.fromJson(String a) =>
415+
CustomStringSerialization(a);
416+
417+
@override
418+
bool operator ==(Object other) =>
419+
other is CustomStringSerialization && a == other.a;
420+
421+
@override
422+
int get hashCode => a.hashCode;
423+
}
424+
425+
class CustomNullableStringSerialization {
426+
final String? a;
427+
428+
CustomNullableStringSerialization(this.a);
429+
430+
String? toJson() => a;
431+
432+
factory CustomNullableStringSerialization.fromJson(String? a) =>
433+
CustomNullableStringSerialization(a);
434+
435+
@override
436+
bool operator ==(Object other) =>
437+
other is CustomNullableStringSerialization && a == other.a;
438+
439+
@override
440+
int get hashCode => a.hashCode;
441+
}
442+
443+
class CustomMapSerialization {
444+
final Map<String, dynamic> a;
445+
446+
CustomMapSerialization(this.a);
447+
448+
Map<String, dynamic> toJson() => a;
449+
450+
factory CustomMapSerialization.fromJson(Map<String, dynamic> a) =>
451+
CustomMapSerialization(a);
452+
453+
@override
454+
bool operator ==(Object other) {
455+
return other is CustomMapSerialization &&
456+
a.toString() == other.a.toString();
457+
}
458+
459+
@override
460+
int get hashCode => a.hashCode;
461+
}

0 commit comments

Comments
 (0)