Skip to content

Commit ab1f7fc

Browse files
cedvdbCommit Queue
authored andcommitted
[json] add datetime support
Closes #57063 GitOrigin-RevId: e8f6591 Change-Id: I83afc47a32e74ea01f3639392cef649aae686076 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394401 Reviewed-by: Jake Macdonald <[email protected]> Commit-Queue: Jake Macdonald <[email protected]>
1 parent f7993d5 commit ab1f7fc

File tree

5 files changed

+66
-5
lines changed

5 files changed

+66
-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.3
2+
3+
- Add support for DateTime, serializing it to an ISO-8601 String.
4+
15
# 0.20.2
26

37
- Fix generated code syntax error when defining fields containing the dollar sign `$` by using raw strings.

pkg/json/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class Manager extends User {
5555

5656
All native JSON types are supported (`int`, `double`, `String`, `bool`, `Null`).
5757

58+
Supports `DateTime`, serializing it to an ISO-8601 String.
59+
5860
The core collection types `List`, `Set`, and `Map` are also supported, if their
5961
elements are supported types. For elements which require more than just a cast,
6062
the type must be statically provided through a generic type argument on the

pkg/json/lib/json.dart

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,16 @@ mixin _FromJson on _Shared {
378378
' as ',
379379
type.code,
380380
]);
381+
case 'DateTime':
382+
return RawCode.fromParts([
383+
if (nullCheck != null) nullCheck,
384+
await builder.resolveIdentifier(_dartCore, 'DateTime'),
385+
'.parse(',
386+
jsonReference,
387+
' as ',
388+
introspectionData.stringCode,
389+
')'
390+
]);
381391
}
382392
}
383393

@@ -511,7 +521,9 @@ mixin _ToJson on _Shared {
511521
if (doNullCheck) '!',
512522
]),
513523
builder,
514-
introspectionData),
524+
introspectionData,
525+
// We already are doing the null check.
526+
omitNullCheck: true),
515527
';\n ',
516528
]);
517529
if (doNullCheck) {
@@ -570,12 +582,16 @@ mixin _ToJson on _Shared {
570582
}
571583

572584
/// Returns a [Code] object which is an expression that converts an instance
573-
/// of type [type] (referenced by [valueReference]) into a JSON map.
585+
/// of type [rawType] (referenced by [valueReference]) into a JSON map.
586+
///
587+
/// Null checks will be inserted if [rawType] is nullable, unless
588+
/// [omitNullCheck] is `true`.
574589
Future<Code> _convertTypeToJson(
575590
TypeAnnotation rawType,
576591
Code valueReference,
577592
DefinitionBuilder builder,
578-
_SharedIntrospectionData introspectionData) async {
593+
_SharedIntrospectionData introspectionData,
594+
{bool omitNullCheck = false}) async {
579595
final type = _checkNamedType(rawType, builder);
580596
if (type == null) {
581597
return RawCode.fromString(
@@ -589,7 +605,7 @@ mixin _ToJson on _Shared {
589605
"throw 'Unable to serialize type ${type.code.debugString}'");
590606
}
591607

592-
var nullCheck = type.isNullable
608+
var nullCheck = type.isNullable && !omitNullCheck
593609
? RawCode.fromParts([
594610
valueReference,
595611
// `null` is a reserved word, we can just use it.
@@ -624,6 +640,8 @@ mixin _ToJson on _Shared {
624640
]);
625641
case 'int' || 'double' || 'num' || 'String' || 'bool':
626642
return valueReference;
643+
case 'DateTime':
644+
return RawCode.fromParts([if (nullCheck != null) nullCheck, valueReference, '.toIso8601String()']);
627645
}
628646
}
629647

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.2
8+
version: 0.20.3
99
environment:
1010
sdk: ^3.6.0-edge
1111
dependencies:

pkg/json/test/json_codable_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ void main() {
1616
'intField': 10,
1717
'doubleField': 12.5,
1818
'numField': 11,
19+
'dateTimeField': '2024-11-11T03:42:29.108308',
1920
'listOfSerializableField': [
2021
{'x': 1},
2122
],
@@ -33,6 +34,7 @@ void main() {
3334
expect(a.intField, 10);
3435
expect(a.doubleField, 12.5);
3536
expect(a.numField, 11);
37+
expect(a.dateTimeField, DateTime.parse('2024-11-11T03:42:29.108308'));
3638
expect(a.listOfSerializableField.single.x, 1);
3739
expect(a.setOfSerializableField.single.x, 2);
3840
expect(a.mapOfSerializableField['c']!.x, 3);
@@ -47,6 +49,7 @@ void main() {
4749
'nullableIntField': 9,
4850
'nullableDoubleField': 11.5,
4951
'nullableNumField': 11.1,
52+
'nullableDateTimeField': '2024-11-11T03:42:29.108308',
5053
'nullableListOfSerializableField': [
5154
{'x': 1},
5255
],
@@ -64,6 +67,8 @@ void main() {
6467
expect(b.nullableIntField, 9);
6568
expect(b.nullableDoubleField, 11.5);
6669
expect(b.nullableNumField, 11.1);
70+
expect(b.nullableDateTimeField,
71+
DateTime.parse('2024-11-11T03:42:29.108308'));
6772
expect(b.nullableListOfSerializableField!.single.x, 1);
6873
expect(b.nullableSetOfSerializableField!.single.x, 2);
6974
expect(b.nullableMapOfSerializableField!['d']!.x, 3);
@@ -78,6 +83,7 @@ void main() {
7883
'nullableIntField': null,
7984
'nullableDoubleField': null,
8085
'nullableNumField': null,
86+
'nullableDateTimeField': null,
8187
'nullableListOfSerializableField': null,
8288
'nullableSetOfSerializableField': null,
8389
'nullableMapOfSerializableField': null,
@@ -87,6 +93,7 @@ void main() {
8793
expect(b.nullableIntField, null);
8894
expect(b.nullableDoubleField, null);
8995
expect(b.nullableNumField, null);
96+
expect(b.nullableDateTimeField, null);
9097
expect(b.nullableListOfSerializableField, null);
9198
expect(b.nullableMapOfSerializableField, null);
9299
expect(b.nullableSetOfSerializableField, null);
@@ -101,6 +108,7 @@ void main() {
101108
expect(b.nullableIntField, null);
102109
expect(b.nullableDoubleField, null);
103110
expect(b.nullableNumField, null);
111+
expect(b.nullableDateTimeField, null);
104112
expect(b.nullableListOfSerializableField, null);
105113
expect(b.nullableMapOfSerializableField, null);
106114
expect(b.nullableSetOfSerializableField, null);
@@ -122,6 +130,7 @@ void main() {
122130

123131
test('collections of nullable objects', () {
124132
var json = {
133+
'listOfNullableDates': [null, '2024-11-11T03:42:29.108308'],
125134
'listOfNullableInts': [null, 1],
126135
'listOfNullableSerializables': [
127136
{'x': 1},
@@ -131,6 +140,10 @@ void main() {
131140
null,
132141
{'a': 1, 'b': null},
133142
],
143+
'setOfNullableDates': [
144+
null,
145+
'2024-11-12T03:42:29.108308',
146+
],
134147
'setOfNullableInts': [
135148
null,
136149
2,
@@ -146,6 +159,10 @@ void main() {
146159
'b': null,
147160
},
148161
],
162+
'mapOfNullableDates': {
163+
'a': '2024-11-13T03:42:29.108308',
164+
'b': null,
165+
},
149166
'mapOfNullableInts': {
150167
'a': 3,
151168
'b': null,
@@ -161,6 +178,8 @@ void main() {
161178
};
162179

163180
var e = E.fromJson(json);
181+
expect(e.listOfNullableDates,
182+
equals([null, DateTime.parse('2024-11-11T03:42:29.108308')]));
164183
expect(e.listOfNullableInts, equals([null, 1]));
165184
expect(e.listOfNullableSerializables.first!.x, 1);
166185
expect(e.listOfNullableSerializables[1], null);
@@ -170,6 +189,8 @@ void main() {
170189
null,
171190
{'a': 1, 'b': null},
172191
]));
192+
expect(e.setOfNullableDates,
193+
equals([null, DateTime.parse('2024-11-12T03:42:29.108308')]));
173194
expect(e.setOfNullableInts, equals({null, 2}));
174195
expect(e.setOfNullableSerializables.first!.x, 2);
175196
expect(e.setOfNullableSerializables.elementAt(1), null);
@@ -182,6 +203,12 @@ void main() {
182203
'b': null,
183204
},
184205
}));
206+
expect(
207+
e.mapOfNullableDates,
208+
equals({
209+
'a': DateTime.parse('2024-11-13T03:42:29.108308'),
210+
'b': null,
211+
}));
185212
expect(
186213
e.mapOfNullableInts,
187214
equals({
@@ -223,6 +250,8 @@ class A {
223250

224251
final num numField;
225252

253+
final DateTime dateTimeField;
254+
226255
final List<C> listOfSerializableField;
227256

228257
final Set<C> setOfSerializableField;
@@ -242,6 +271,8 @@ class B {
242271

243272
final num? nullableNumField;
244273

274+
final DateTime? nullableDateTimeField;
275+
245276
final List<C>? nullableListOfSerializableField;
246277

247278
final Set<C>? nullableSetOfSerializableField;
@@ -261,18 +292,24 @@ class D extends C {
261292

262293
@JsonCodable()
263294
class E {
295+
final List<DateTime?> listOfNullableDates;
296+
264297
final List<int?> listOfNullableInts;
265298

266299
final List<C?> listOfNullableSerializables;
267300

268301
final List<Map<String, int?>?> listOfNullableMapsOfNullableInts;
269302

303+
final Set<DateTime?> setOfNullableDates;
304+
270305
final Set<int?> setOfNullableInts;
271306

272307
final Set<C?> setOfNullableSerializables;
273308

274309
final Set<Map<String, int?>?> setOfNullableMapsOfNullableInts;
275310

311+
final Map<String, DateTime?> mapOfNullableDates;
312+
276313
final Map<String, int?> mapOfNullableInts;
277314

278315
final Map<String, C?> mapOfNullableSerializables;

0 commit comments

Comments
 (0)