Skip to content

Commit f27df2a

Browse files
committed
Add JsonSerializabel.constructor
Allows specifying an alternative constructor to invoke when creating a `fromJson` helper. Closes #490
1 parent 73eac23 commit f27df2a

24 files changed

+238
-91
lines changed

json_annotation/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 4.2.0-dev
2+
3+
- Added `JsonSerializabel.constructor` field to allow specifying an alternative
4+
constructor to invoke when creating a `fromJson` helper.
5+
16
## 4.1.0
27

38
- Added a `const` constructor to `JsonConverter`.

json_annotation/lib/src/json_serializable.dart

+12
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ class JsonSerializable {
5050
/// [CheckedFromJsonException] is thrown.
5151
final bool? checked;
5252

53+
/// Specifies a named constructor to target when creating the `fromJson`
54+
/// function.
55+
///
56+
/// If the value is not set or an empty [String], the default constructor
57+
/// is used.
58+
///
59+
/// This setting has no effect if [createFactory] is `false`.
60+
final String? constructor;
61+
5362
/// If `true` (the default), a private, static `_$ExampleFromJson` method
5463
/// is created in the generated part file.
5564
///
@@ -182,6 +191,7 @@ class JsonSerializable {
182191
@Deprecated('Has no effect') bool? nullable,
183192
this.anyMap,
184193
this.checked,
194+
this.constructor,
185195
this.createFactory,
186196
this.createToJson,
187197
this.disallowUnrecognizedKeys,
@@ -201,6 +211,7 @@ class JsonSerializable {
201211
static const defaults = JsonSerializable(
202212
anyMap: false,
203213
checked: false,
214+
constructor: '',
204215
createFactory: true,
205216
createToJson: true,
206217
disallowUnrecognizedKeys: false,
@@ -220,6 +231,7 @@ class JsonSerializable {
220231
JsonSerializable withDefaults() => JsonSerializable(
221232
anyMap: anyMap ?? defaults.anyMap,
222233
checked: checked ?? defaults.checked,
234+
constructor: constructor ?? defaults.constructor,
223235
createFactory: createFactory ?? defaults.createFactory,
224236
createToJson: createToJson ?? defaults.createToJson,
225237
disallowUnrecognizedKeys:

json_annotation/lib/src/json_serializable.g.dart

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

json_annotation/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: json_annotation
2-
version: 4.1.0
2+
version: 4.2.0-dev
33
description: >-
44
Classes and helper functions that support JSON code generation via the
55
`json_serializable` package.

json_serializable/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 5.1.0-dev
2+
3+
- Added support for `JsonSerializabel.constructor` to allow specifying an
4+
alternative constructor to invoke when creating a `fromJson` helper.
5+
- Require `json_annotation` `'>=4.2.0 <4.3.0'`.
6+
17
## 5.0.2
28

39
- Include type arguments when invoking `fromJson` on custom types.

json_serializable/README.md

+23-19
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ is generated:
8686
| -------------------------- | ------------------------------------------- | --------------------------- |
8787
| any_map | [JsonSerializable.anyMap] | |
8888
| checked | [JsonSerializable.checked] | |
89+
| constructor | [JsonSerializable.constructor] | |
8990
| create_factory | [JsonSerializable.createFactory] | |
9091
| create_to_json | [JsonSerializable.createToJson] | |
9192
| disallow_unrecognized_keys | [JsonSerializable.disallowUnrecognizedKeys] | |
@@ -103,25 +104,27 @@ is generated:
103104
| | | [JsonKey.toJson] |
104105
| | | [JsonKey.unknownEnumValue] |
105106

106-
[JsonSerializable.anyMap]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/anyMap.html
107-
[JsonSerializable.checked]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/checked.html
108-
[JsonSerializable.createFactory]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/createFactory.html
109-
[JsonSerializable.createToJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/createToJson.html
110-
[JsonSerializable.disallowUnrecognizedKeys]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/disallowUnrecognizedKeys.html
111-
[JsonSerializable.explicitToJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/explicitToJson.html
112-
[JsonSerializable.fieldRename]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/fieldRename.html
113-
[JsonSerializable.genericArgumentFactories]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/genericArgumentFactories.html
114-
[JsonSerializable.ignoreUnannotated]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/ignoreUnannotated.html
115-
[JsonSerializable.includeIfNull]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/includeIfNull.html
116-
[JsonKey.includeIfNull]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/includeIfNull.html
117-
[JsonKey.defaultValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/defaultValue.html
118-
[JsonKey.disallowNullValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/disallowNullValue.html
119-
[JsonKey.fromJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/fromJson.html
120-
[JsonKey.ignore]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/ignore.html
121-
[JsonKey.name]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/name.html
122-
[JsonKey.required]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/required.html
123-
[JsonKey.toJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/toJson.html
124-
[JsonKey.unknownEnumValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/unknownEnumValue.html
107+
[JsonSerializable.anyMap]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/anyMap.html
108+
[JsonSerializable.checked]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/checked.html
109+
[JsonSerializable.constructor]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/constructor.html
110+
[JsonSerializable.createFactory]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/createFactory.html
111+
[JsonSerializable.createToJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/createToJson.html
112+
[JsonSerializable.disallowUnrecognizedKeys]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/disallowUnrecognizedKeys.html
113+
[JsonSerializable.explicitToJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/explicitToJson.html
114+
[JsonSerializable.fieldRename]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/fieldRename.html
115+
[JsonSerializable.genericArgumentFactories]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html
116+
[JsonSerializable.ignoreUnannotated]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/ignoreUnannotated.html
117+
[JsonSerializable.includeIfNull]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/includeIfNull.html
118+
[JsonKey.includeIfNull]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/includeIfNull.html
119+
[JsonKey.defaultValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/defaultValue.html
120+
[JsonKey.disallowNullValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/disallowNullValue.html
121+
[JsonKey.fromJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
122+
[JsonKey.ignore]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/ignore.html
123+
[JsonKey.name]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/name.html
124+
[JsonKey.required]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/required.html
125+
[JsonKey.toJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
126+
[JsonKey.unknownEnumValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/unknownEnumValue.html
127+
125128

126129
> Note: every `JsonSerializable` field is configurable via `build.yaml`
127130
> see the table for the corresponding key.
@@ -151,6 +154,7 @@ targets:
151154
# The default value for each is listed.
152155
any_map: false
153156
checked: false
157+
constructor: ''
154158
create_factory: true
155159
create_to_json: true
156160
disallow_unrecognized_keys: false

json_serializable/doc/doc.md

+21-19
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
| -------------------------- | ------------------------------------------- | --------------------------- |
33
| any_map | [JsonSerializable.anyMap] | |
44
| checked | [JsonSerializable.checked] | |
5+
| constructor | [JsonSerializable.constructor] | |
56
| create_factory | [JsonSerializable.createFactory] | |
67
| create_to_json | [JsonSerializable.createToJson] | |
78
| disallow_unrecognized_keys | [JsonSerializable.disallowUnrecognizedKeys] | |
@@ -19,22 +20,23 @@
1920
| | | [JsonKey.toJson] |
2021
| | | [JsonKey.unknownEnumValue] |
2122

22-
[JsonSerializable.anyMap]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/anyMap.html
23-
[JsonSerializable.checked]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/checked.html
24-
[JsonSerializable.createFactory]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/createFactory.html
25-
[JsonSerializable.createToJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/createToJson.html
26-
[JsonSerializable.disallowUnrecognizedKeys]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/disallowUnrecognizedKeys.html
27-
[JsonSerializable.explicitToJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/explicitToJson.html
28-
[JsonSerializable.fieldRename]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/fieldRename.html
29-
[JsonSerializable.genericArgumentFactories]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/genericArgumentFactories.html
30-
[JsonSerializable.ignoreUnannotated]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/ignoreUnannotated.html
31-
[JsonSerializable.includeIfNull]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonSerializable/includeIfNull.html
32-
[JsonKey.includeIfNull]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/includeIfNull.html
33-
[JsonKey.defaultValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/defaultValue.html
34-
[JsonKey.disallowNullValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/disallowNullValue.html
35-
[JsonKey.fromJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/fromJson.html
36-
[JsonKey.ignore]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/ignore.html
37-
[JsonKey.name]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/name.html
38-
[JsonKey.required]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/required.html
39-
[JsonKey.toJson]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/toJson.html
40-
[JsonKey.unknownEnumValue]: https://pub.dev/documentation/json_annotation/4.1.0/json_annotation/JsonKey/unknownEnumValue.html
23+
[JsonSerializable.anyMap]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/anyMap.html
24+
[JsonSerializable.checked]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/checked.html
25+
[JsonSerializable.constructor]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/constructor.html
26+
[JsonSerializable.createFactory]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/createFactory.html
27+
[JsonSerializable.createToJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/createToJson.html
28+
[JsonSerializable.disallowUnrecognizedKeys]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/disallowUnrecognizedKeys.html
29+
[JsonSerializable.explicitToJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/explicitToJson.html
30+
[JsonSerializable.fieldRename]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/fieldRename.html
31+
[JsonSerializable.genericArgumentFactories]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html
32+
[JsonSerializable.ignoreUnannotated]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/ignoreUnannotated.html
33+
[JsonSerializable.includeIfNull]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/includeIfNull.html
34+
[JsonKey.includeIfNull]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/includeIfNull.html
35+
[JsonKey.defaultValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/defaultValue.html
36+
[JsonKey.disallowNullValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/disallowNullValue.html
37+
[JsonKey.fromJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
38+
[JsonKey.ignore]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/ignore.html
39+
[JsonKey.name]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/name.html
40+
[JsonKey.required]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/required.html
41+
[JsonKey.toJson]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
42+
[JsonKey.unknownEnumValue]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/unknownEnumValue.html

json_serializable/lib/src/decode_helper.dart

+10-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ abstract class DecodeHelper implements HelperCore {
5858

5959
final data = _writeConstructorInvocation(
6060
element,
61+
config.constructor,
6162
accessibleFields.keys,
6263
accessibleFields.values
6364
.where((fe) => element.lookUpSetter(fe.name, element.library) != null)
@@ -242,6 +243,7 @@ abstract class DecodeHelper implements HelperCore {
242243
/// been defined by a constructor parameter with the same name.
243244
_ConstructorData _writeConstructorInvocation(
244245
ClassElement classElement,
246+
String constructorName,
245247
Iterable<String> availableConstructorParameters,
246248
Iterable<String> writableFields,
247249
Map<String, String> unavailableReasons,
@@ -250,7 +252,7 @@ _ConstructorData _writeConstructorInvocation(
250252
) {
251253
final className = classElement.name;
252254

253-
final ctor = unnamedConstructorOrError(classElement);
255+
final ctor = constructorByName(classElement, constructorName);
254256

255257
final usedCtorParamsAndFields = <String>{};
256258
final constructorArguments = <ParameterElement>[];
@@ -287,8 +289,14 @@ _ConstructorData _writeConstructorInvocation(
287289
final remainingFieldsForInvocationBody =
288290
writableFields.toSet().difference(usedCtorParamsAndFields);
289291

292+
final constructorExtra = constructorName.isEmpty ? '' : '.$constructorName';
293+
290294
final buffer = StringBuffer()
291-
..write('$className${genericClassArguments(classElement, false)}(');
295+
..write(
296+
'$className'
297+
'${genericClassArguments(classElement, false)}'
298+
'$constructorExtra(',
299+
);
292300
if (constructorArguments.isNotEmpty) {
293301
buffer
294302
..writeln()

json_serializable/lib/src/settings.dart

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class Settings {
4949
ClassConfig get config => ClassConfig(
5050
checked: _config.checked ?? ClassConfig.defaults.checked,
5151
anyMap: _config.anyMap ?? ClassConfig.defaults.anyMap,
52+
constructor: _config.constructor ?? ClassConfig.defaults.constructor,
5253
createFactory:
5354
_config.createFactory ?? ClassConfig.defaults.createFactory,
5455
createToJson: _config.createToJson ?? ClassConfig.defaults.createToJson,

json_serializable/lib/src/type_helpers/config_types.dart

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ class ClassConfig implements JsonSerializable {
4242
@override
4343
final bool checked;
4444

45+
@override
46+
final String constructor;
47+
4548
@override
4649
final bool createFactory;
4750

@@ -71,6 +74,7 @@ class ClassConfig implements JsonSerializable {
7174
const ClassConfig({
7275
required this.anyMap,
7376
required this.checked,
77+
required this.constructor,
7478
required this.createFactory,
7579
required this.createToJson,
7680
required this.disallowUnrecognizedKeys,
@@ -87,6 +91,7 @@ class ClassConfig implements JsonSerializable {
8791
static const defaults = ClassConfig(
8892
anyMap: false,
8993
checked: false,
94+
constructor: '',
9095
createFactory: true,
9196
createToJson: true,
9297
disallowUnrecognizedKeys: false,
@@ -116,6 +121,7 @@ Map<String, dynamic> _$JsonSerializableToJson(JsonSerializable instance) =>
116121
<String, dynamic>{
117122
'any_map': instance.anyMap,
118123
'checked': instance.checked,
124+
'constructor': instance.constructor,
119125
'create_factory': instance.createFactory,
120126
'create_to_json': instance.createToJson,
121127
'disallow_unrecognized_keys': instance.disallowUnrecognizedKeys,

0 commit comments

Comments
 (0)