Skip to content

Commit b509a7f

Browse files
authored
Include type arguments when invoking fromJson on custom types. (google#984)
This fixes an edge case where the generic arguments could not be inferred. Also DRY'd up some test helpers Fixes google#980 Closes google#981
1 parent 12fe7a1 commit b509a7f

16 files changed

+98
-27
lines changed

json_serializable/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 5.0.2
2+
3+
- Include type arguments when invoking `fromJson` on custom types.
4+
This fixes an edge case where the generic arguments could not be inferred.
5+
16
## 5.0.1
27

38
- Correctly handle nullable custom objects within `Iterable` and `Map`.

json_serializable/lib/src/type_helpers/json_helper.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:source_gen/source_gen.dart';
1111
import 'package:source_helper/source_helper.dart';
1212

1313
import '../default_container.dart';
14+
import '../helper_core.dart';
1415
import '../type_helper.dart';
1516
import '../utils.dart';
1617
import 'config_types.dart';
@@ -130,7 +131,7 @@ class JsonHelper extends TypeHelper<TypeHelperContextWithConfig> {
130131

131132
// TODO: the type could be imported from a library with a prefix!
132133
// https://github.com/google/json_serializable.dart/issues/19
133-
output = '${targetType.element.name}.fromJson($output)';
134+
output = '${typeToCode(targetType.promoteNonNullable())}.fromJson($output)';
134135

135136
return DefaultContainer(expression, output);
136137
}

json_serializable/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: json_serializable
2-
version: 5.0.1
2+
version: 5.0.2
33
description: >-
44
Automatically generate code for converting to and from JSON by annotating
55
Dart classes.

json_serializable/test/generic_files/generic_argument_factories.g.dart

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

json_serializable/test/generic_files/generic_argument_factories_nullable.g.dart

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

json_serializable/test/generic_files/generic_class.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
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+
import 'package:collection/collection.dart';
56
import 'package:json_annotation/json_annotation.dart';
67

8+
import '../test_utils.dart';
9+
710
part 'generic_class.g.dart';
811

912
@JsonSerializable()
@@ -103,3 +106,40 @@ class _DurationListMillisecondConverter
103106
int? toJson(List<Duration>? object) =>
104107
object?.fold<int>(0, (sum, obj) => sum + obj.inMilliseconds);
105108
}
109+
110+
class Issue980GenericClass<T> {
111+
final T value;
112+
113+
Issue980GenericClass(this.value);
114+
115+
factory Issue980GenericClass.fromJson(Map<String, dynamic> json) =>
116+
Issue980GenericClass(json['value'] as T);
117+
118+
Map<String, dynamic> toJson() => {'value': value};
119+
120+
@override
121+
bool operator ==(Object other) =>
122+
other is Issue980GenericClass && value == other.value;
123+
124+
@override
125+
int get hashCode => value.hashCode;
126+
}
127+
128+
@JsonSerializable()
129+
class Issue980ParentClass {
130+
final List<Issue980GenericClass<int>> list;
131+
132+
Issue980ParentClass(this.list);
133+
134+
factory Issue980ParentClass.fromJson(Map<String, dynamic> json) =>
135+
_$Issue980ParentClassFromJson(json);
136+
137+
Map<String, dynamic> toJson() => _$Issue980ParentClassToJson(this);
138+
139+
@override
140+
bool operator ==(Object other) =>
141+
other is Issue980ParentClass && deepEquals(list, other.list);
142+
143+
@override
144+
int get hashCode => const DeepCollectionEquality().hash(list);
145+
}

json_serializable/test/generic_files/generic_class.g.dart

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

json_serializable/test/generic_files/generic_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,14 @@ void main() {
316316
});
317317
});
318318
});
319+
320+
test('issue 980 regression test', () {
321+
roundTripObject(
322+
Issue980ParentClass([
323+
Issue980GenericClass(45),
324+
Issue980GenericClass(42),
325+
]),
326+
(json) => Issue980ParentClass.fromJson(json),
327+
);
328+
});
319329
}

json_serializable/test/integration/json_test_common.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:collection';
66

7-
import 'package:collection/collection.dart';
87
import 'package:json_annotation/json_annotation.dart';
98

109
enum Category {
@@ -42,9 +41,6 @@ DateTime? dateTimeFromEpochUs(int? us) =>
4241

4342
int? dateTimeToEpochUs(DateTime? dateTime) => dateTime?.microsecondsSinceEpoch;
4443

45-
bool deepEquals(dynamic a, dynamic b) =>
46-
const DeepCollectionEquality().equals(a, b);
47-
4844
class Platform {
4945
final String description;
5046

json_serializable/test/integration/json_test_example.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:collection';
77

88
import 'package:json_annotation/json_annotation.dart';
99

10+
import '../test_utils.dart';
1011
import 'json_test_common.dart';
1112

1213
part 'json_test_example.g.dart';

0 commit comments

Comments
 (0)