Skip to content

Commit

Permalink
[json] add datetime support
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
cedvdb authored and Commit Queue committed Nov 21, 2024
1 parent f7993d5 commit ab1f7fc
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 5 deletions.
4 changes: 4 additions & 0 deletions pkg/json/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 0.20.3

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

# 0.20.2

- Fix generated code syntax error when defining fields containing the dollar sign `$` by using raw strings.
Expand Down
2 changes: 2 additions & 0 deletions pkg/json/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class Manager extends User {

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

Supports `DateTime`, serializing it to an ISO-8601 String.

The core collection types `List`, `Set`, and `Map` are also supported, if their
elements are supported types. For elements which require more than just a cast,
the type must be statically provided through a generic type argument on the
Expand Down
26 changes: 22 additions & 4 deletions pkg/json/lib/json.dart
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,16 @@ mixin _FromJson on _Shared {
' as ',
type.code,
]);
case 'DateTime':
return RawCode.fromParts([
if (nullCheck != null) nullCheck,
await builder.resolveIdentifier(_dartCore, 'DateTime'),
'.parse(',
jsonReference,
' as ',
introspectionData.stringCode,
')'
]);
}
}

Expand Down Expand Up @@ -511,7 +521,9 @@ mixin _ToJson on _Shared {
if (doNullCheck) '!',
]),
builder,
introspectionData),
introspectionData,
// We already are doing the null check.
omitNullCheck: true),
';\n ',
]);
if (doNullCheck) {
Expand Down Expand Up @@ -570,12 +582,16 @@ mixin _ToJson on _Shared {
}

/// Returns a [Code] object which is an expression that converts an instance
/// of type [type] (referenced by [valueReference]) into a JSON map.
/// of type [rawType] (referenced by [valueReference]) into a JSON map.
///
/// Null checks will be inserted if [rawType] is nullable, unless
/// [omitNullCheck] is `true`.
Future<Code> _convertTypeToJson(
TypeAnnotation rawType,
Code valueReference,
DefinitionBuilder builder,
_SharedIntrospectionData introspectionData) async {
_SharedIntrospectionData introspectionData,
{bool omitNullCheck = false}) async {
final type = _checkNamedType(rawType, builder);
if (type == null) {
return RawCode.fromString(
Expand All @@ -589,7 +605,7 @@ mixin _ToJson on _Shared {
"throw 'Unable to serialize type ${type.code.debugString}'");
}

var nullCheck = type.isNullable
var nullCheck = type.isNullable && !omitNullCheck
? RawCode.fromParts([
valueReference,
// `null` is a reserved word, we can just use it.
Expand Down Expand Up @@ -624,6 +640,8 @@ mixin _ToJson on _Shared {
]);
case 'int' || 'double' || 'num' || 'String' || 'bool':
return valueReference;
case 'DateTime':
return RawCode.fromParts([if (nullCheck != null) nullCheck, valueReference, '.toIso8601String()']);
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/json/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: >
`toJson` encoding method.
repository: https://github.com/dart-lang/sdk/tree/main/pkg/json
version: 0.20.2
version: 0.20.3
environment:
sdk: ^3.6.0-edge
dependencies:
Expand Down
37 changes: 37 additions & 0 deletions pkg/json/test/json_codable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void main() {
'intField': 10,
'doubleField': 12.5,
'numField': 11,
'dateTimeField': '2024-11-11T03:42:29.108308',
'listOfSerializableField': [
{'x': 1},
],
Expand All @@ -33,6 +34,7 @@ void main() {
expect(a.intField, 10);
expect(a.doubleField, 12.5);
expect(a.numField, 11);
expect(a.dateTimeField, DateTime.parse('2024-11-11T03:42:29.108308'));
expect(a.listOfSerializableField.single.x, 1);
expect(a.setOfSerializableField.single.x, 2);
expect(a.mapOfSerializableField['c']!.x, 3);
Expand All @@ -47,6 +49,7 @@ void main() {
'nullableIntField': 9,
'nullableDoubleField': 11.5,
'nullableNumField': 11.1,
'nullableDateTimeField': '2024-11-11T03:42:29.108308',
'nullableListOfSerializableField': [
{'x': 1},
],
Expand All @@ -64,6 +67,8 @@ void main() {
expect(b.nullableIntField, 9);
expect(b.nullableDoubleField, 11.5);
expect(b.nullableNumField, 11.1);
expect(b.nullableDateTimeField,
DateTime.parse('2024-11-11T03:42:29.108308'));
expect(b.nullableListOfSerializableField!.single.x, 1);
expect(b.nullableSetOfSerializableField!.single.x, 2);
expect(b.nullableMapOfSerializableField!['d']!.x, 3);
Expand All @@ -78,6 +83,7 @@ void main() {
'nullableIntField': null,
'nullableDoubleField': null,
'nullableNumField': null,
'nullableDateTimeField': null,
'nullableListOfSerializableField': null,
'nullableSetOfSerializableField': null,
'nullableMapOfSerializableField': null,
Expand All @@ -87,6 +93,7 @@ void main() {
expect(b.nullableIntField, null);
expect(b.nullableDoubleField, null);
expect(b.nullableNumField, null);
expect(b.nullableDateTimeField, null);
expect(b.nullableListOfSerializableField, null);
expect(b.nullableMapOfSerializableField, null);
expect(b.nullableSetOfSerializableField, null);
Expand All @@ -101,6 +108,7 @@ void main() {
expect(b.nullableIntField, null);
expect(b.nullableDoubleField, null);
expect(b.nullableNumField, null);
expect(b.nullableDateTimeField, null);
expect(b.nullableListOfSerializableField, null);
expect(b.nullableMapOfSerializableField, null);
expect(b.nullableSetOfSerializableField, null);
Expand All @@ -122,6 +130,7 @@ void main() {

test('collections of nullable objects', () {
var json = {
'listOfNullableDates': [null, '2024-11-11T03:42:29.108308'],
'listOfNullableInts': [null, 1],
'listOfNullableSerializables': [
{'x': 1},
Expand All @@ -131,6 +140,10 @@ void main() {
null,
{'a': 1, 'b': null},
],
'setOfNullableDates': [
null,
'2024-11-12T03:42:29.108308',
],
'setOfNullableInts': [
null,
2,
Expand All @@ -146,6 +159,10 @@ void main() {
'b': null,
},
],
'mapOfNullableDates': {
'a': '2024-11-13T03:42:29.108308',
'b': null,
},
'mapOfNullableInts': {
'a': 3,
'b': null,
Expand All @@ -161,6 +178,8 @@ void main() {
};

var e = E.fromJson(json);
expect(e.listOfNullableDates,
equals([null, DateTime.parse('2024-11-11T03:42:29.108308')]));
expect(e.listOfNullableInts, equals([null, 1]));
expect(e.listOfNullableSerializables.first!.x, 1);
expect(e.listOfNullableSerializables[1], null);
Expand All @@ -170,6 +189,8 @@ void main() {
null,
{'a': 1, 'b': null},
]));
expect(e.setOfNullableDates,
equals([null, DateTime.parse('2024-11-12T03:42:29.108308')]));
expect(e.setOfNullableInts, equals({null, 2}));
expect(e.setOfNullableSerializables.first!.x, 2);
expect(e.setOfNullableSerializables.elementAt(1), null);
Expand All @@ -182,6 +203,12 @@ void main() {
'b': null,
},
}));
expect(
e.mapOfNullableDates,
equals({
'a': DateTime.parse('2024-11-13T03:42:29.108308'),
'b': null,
}));
expect(
e.mapOfNullableInts,
equals({
Expand Down Expand Up @@ -223,6 +250,8 @@ class A {

final num numField;

final DateTime dateTimeField;

final List<C> listOfSerializableField;

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

final num? nullableNumField;

final DateTime? nullableDateTimeField;

final List<C>? nullableListOfSerializableField;

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

@JsonCodable()
class E {
final List<DateTime?> listOfNullableDates;

final List<int?> listOfNullableInts;

final List<C?> listOfNullableSerializables;

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

final Set<DateTime?> setOfNullableDates;

final Set<int?> setOfNullableInts;

final Set<C?> setOfNullableSerializables;

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

final Map<String, DateTime?> mapOfNullableDates;

final Map<String, int?> mapOfNullableInts;

final Map<String, C?> mapOfNullableSerializables;
Expand Down

0 comments on commit ab1f7fc

Please sign in to comment.