Skip to content

Commit 26b5ced

Browse files
committed
Starting default values
Progress on #74
1 parent c78b548 commit 26b5ced

17 files changed

+400
-13
lines changed

json_annotation/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.2.6
2+
3+
* Added `JsonKey.defaultValue`.
4+
15
## 0.2.5
26

37
* Added `CheckedFromJsonException` which is thrown by code generated when

json_annotation/lib/src/json_serializable.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ class JsonKey {
117117
/// Values returned by [toJson] should "round-trip" through [fromJson].
118118
final Function toJson;
119119

120+
/// The value to use if the source JSON does not contain this key or if the
121+
/// value is `null`.
122+
final Object defaultValue;
123+
120124
/// Creates a new [JsonKey] instance.
121125
///
122126
/// Only required when the default behavior is not desired.
@@ -126,5 +130,6 @@ class JsonKey {
126130
this.includeIfNull,
127131
this.ignore,
128132
this.fromJson,
129-
this.toJson});
133+
this.toJson,
134+
this.defaultValue});
130135
}

json_annotation/pubspec.yaml

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

json_serializable/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 0.5.5
22

3+
* Added support for `JsonKey.defaultValue`.
4+
35
* Small change to how nullable `Map` values are deserialized.
46

57
## 0.5.4+1

json_serializable/lib/src/generator_helper.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,22 +382,31 @@ class ${_wrapperClassName(true)} extends \$JsonMapWrapper {
382382
String _deserializeForField(FieldElement field,
383383
{ParameterElement ctorParam, bool checkedProperty}) {
384384
checkedProperty ??= false;
385-
var jsonKey = _safeNameAccess(field);
385+
var defaultValue = jsonKeyFor(field).defaultValue;
386+
var jsonKeyName = _safeNameAccess(field);
386387

387388
var targetType = ctorParam?.type ?? field.type;
388389

389390
try {
390391
if (_generator.checked) {
392+
// TODO: default value fun here!
391393
var value = _getHelperContext(field).deserialize(targetType, 'v');
392394
if (checkedProperty) {
393395
return value;
394396
}
395397

396-
return '\$checkedConvert(json, $jsonKey, (v) => $value)';
398+
return '\$checkedConvert(json, $jsonKeyName, (v) => $value)';
397399
}
398400
assert(!checkedProperty,
399401
'should only be true if `_generator.checked` is true.');
400-
return _getHelperContext(field).deserialize(targetType, 'json[$jsonKey]');
402+
403+
var value = _getHelperContext(field)
404+
.deserialize(targetType, 'json[$jsonKeyName]');
405+
406+
if (defaultValue != null) {
407+
value = '$value ?? $defaultValue';
408+
}
409+
return value;
401410
} on UnsupportedTypeError catch (e) {
402411
throw _createInvalidGenerationError('fromJson', field, e);
403412
}

json_serializable/lib/src/json_key_helpers.dart

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import 'package:json_annotation/json_annotation.dart';
1010
import 'package:meta/meta.dart' show alwaysThrows;
1111
import 'package:source_gen/source_gen.dart';
1212

13+
import 'json_literal_generator.dart';
14+
1315
@alwaysThrows
1416
T _throwUnsupported<T>(FieldElement element, String message) =>
1517
throw new InvalidGenerationSourceError(
@@ -43,11 +45,49 @@ JsonKeyWithConversion _from(FieldElement element) {
4345
var fromJsonName = _getFunctionName(obj, element, true);
4446
var toJsonName = _getFunctionName(obj, element, false);
4547

48+
Object _getLiteral(DartObject dartObject) {
49+
if (dartObject.isNull) {
50+
return null;
51+
}
52+
53+
var reader = new ConstantReader(dartObject);
54+
55+
if (reader.isSymbol) {
56+
_throwUnsupported(element,
57+
'Values of type `Symbol` are not supported for `defaultValue`.');
58+
} else if (reader.isType) {
59+
_throwUnsupported(element,
60+
'Values of type `Type` are not supported for `defaultValue`.');
61+
} else if (!reader.isLiteral) {
62+
_throwUnsupported(
63+
element, 'The provided `defaultValue` is not a literal: $dartObject');
64+
}
65+
66+
var literal = reader.literalValue;
67+
if (literal is num || literal is String || literal is bool) {
68+
return literal;
69+
} else if (literal is List<DartObject>) {
70+
return literal.map(_getLiteral).toList();
71+
} else if (literal is Map<DartObject, DartObject>) {
72+
return literal
73+
.map((k, v) => new MapEntry(_getLiteral(k), _getLiteral(v)));
74+
}
75+
_throwUnsupported(
76+
element, 'The provided value is not supported: $dartObject');
77+
}
78+
79+
var defaultValueLiteral = _getLiteral(obj.getField('defaultValue'));
80+
81+
if (defaultValueLiteral != null) {
82+
defaultValueLiteral = jsonLiteralAsDart(defaultValueLiteral, false);
83+
}
84+
4685
return new JsonKeyWithConversion._(
4786
obj.getField('name').toStringValue(),
4887
obj.getField('nullable').toBoolValue(),
4988
obj.getField('includeIfNull').toBoolValue(),
5089
obj.getField('ignore').toBoolValue(),
90+
defaultValueLiteral,
5191
fromJsonName,
5292
toJsonName);
5393
}
@@ -69,12 +109,13 @@ class JsonKeyWithConversion extends JsonKey {
69109
super();
70110

71111
JsonKeyWithConversion._(String name, bool nullable, bool includeIfNull,
72-
bool ignore, this.fromJsonData, this.toJsonData)
112+
bool ignore, Object defaultValue, this.fromJsonData, this.toJsonData)
73113
: super(
74114
name: name,
75115
nullable: nullable,
76116
includeIfNull: includeIfNull,
77-
ignore: ignore);
117+
ignore: ignore,
118+
defaultValue: defaultValue);
78119
}
79120

80121
ConvertData _getFunctionName(

json_serializable/lib/src/json_literal_generator.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class JsonLiteralGenerator extends GeneratorForAnnotation<JsonLiteral> {
3232

3333
var asConst = annotation.read('asConst').boolValue;
3434

35-
var thing = _jsonLiteralAsDart(content, asConst).toString();
35+
var thing = jsonLiteralAsDart(content, asConst).toString();
3636
var marked = asConst ? 'const' : 'final';
3737

3838
return '$marked _\$${element.name}JsonLiteral = $thing;';
@@ -43,16 +43,15 @@ class JsonLiteralGenerator extends GeneratorForAnnotation<JsonLiteral> {
4343
///
4444
/// If [asConst] is `true`, the returned [String] is encoded as a `const`
4545
/// literal.
46-
String _jsonLiteralAsDart(dynamic value, bool asConst) {
46+
String jsonLiteralAsDart(dynamic value, bool asConst) {
4747
if (value == null) return 'null';
4848

4949
if (value is String) return escapeDartString(value);
5050

5151
if (value is bool || value is num) return value.toString();
5252

5353
if (value is List) {
54-
var listItems =
55-
value.map((v) => _jsonLiteralAsDart(v, asConst)).join(',\n');
54+
var listItems = value.map((v) => jsonLiteralAsDart(v, asConst)).join(',\n');
5655
return '${asConst ? 'const' : ''}[$listItems]';
5756
}
5857

@@ -78,7 +77,7 @@ String jsonMapAsDart(Map<String, dynamic> value, bool asConst) {
7877
}
7978
buffer.write(escapeDartString(k));
8079
buffer.write(':');
81-
buffer.write(_jsonLiteralAsDart(v, asConst));
80+
buffer.write(jsonLiteralAsDart(v, asConst));
8281
});
8382

8483
buffer.write('}');

json_serializable/pubspec.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dependencies:
1212

1313
# Use a tight version constraint to ensure that a constraint on
1414
# `json_annotation`. Properly constrains all features it provides.
15-
json_annotation: '>=0.2.5 <0.2.6'
15+
json_annotation: '>=0.2.6 <0.2.7'
1616
meta: ^1.1.0
1717
path: ^1.3.2
1818
source_gen: '>=0.8.1 <0.9.0'
@@ -24,3 +24,7 @@ dev_dependencies:
2424
logging: ^0.11.3+1
2525
test: ^0.12.3
2626
yaml: ^2.1.13
27+
28+
dependency_overrides:
29+
json_annotation:
30+
path: ../json_annotation
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// ignore_for_file: annotate_overrides
6+
7+
import 'package:json_annotation/json_annotation.dart';
8+
9+
part 'default_value.g.dart';
10+
11+
const _intValue = 42;
12+
13+
@JsonSerializable()
14+
class DefaultValue extends Object with _$DefaultValueSerializerMixin {
15+
@JsonKey(defaultValue: true)
16+
bool fieldBool;
17+
18+
@JsonKey(defaultValue: 'string')
19+
String fieldString;
20+
21+
@JsonKey(defaultValue: _intValue)
22+
int fieldInt;
23+
24+
@JsonKey(defaultValue: 3.14)
25+
double fieldDouble;
26+
27+
@JsonKey(defaultValue: [])
28+
List fieldListEmpty;
29+
30+
@JsonKey(defaultValue: {})
31+
Map fieldMapEmpty;
32+
33+
@JsonKey(defaultValue: [1, 2, 3])
34+
List<int> fieldListSimple;
35+
36+
@JsonKey(defaultValue: {'answer': 42})
37+
Map<String, int> fieldMapSimple;
38+
39+
@JsonKey(defaultValue: {
40+
'root': ['child']
41+
})
42+
Map<String, List<String>> fieldMapListString;
43+
44+
DefaultValue();
45+
46+
factory DefaultValue.fromJson(Map<String, dynamic> json) =>
47+
_$DefaultValueFromJson(json);
48+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// GENERATED CODE - DO NOT MODIFY BY HAND
6+
7+
part of 'default_value.dart';
8+
9+
// **************************************************************************
10+
// Generator: JsonSerializableGenerator
11+
// **************************************************************************
12+
13+
DefaultValue _$DefaultValueFromJson(Map<String, dynamic> json) =>
14+
new DefaultValue()
15+
..fieldBool = json['fieldBool'] as bool ?? true
16+
..fieldString = json['fieldString'] as String ?? 'string'
17+
..fieldInt = json['fieldInt'] as int ?? 42
18+
..fieldDouble = (json['fieldDouble'] as num)?.toDouble() ?? 3.14
19+
..fieldListEmpty = json['fieldListEmpty'] as List ?? []
20+
..fieldMapEmpty = json['fieldMapEmpty'] as Map<String, dynamic> ?? {}
21+
..fieldListSimple =
22+
(json['fieldListSimple'] as List)?.map((e) => e as int)?.toList() ??
23+
[1, 2, 3]
24+
..fieldMapSimple = (json['fieldMapSimple'] as Map<String, dynamic>)
25+
?.map((k, e) => new MapEntry(k, e as int)) ??
26+
{'answer': 42}
27+
..fieldMapListString =
28+
(json['fieldMapListString'] as Map<String, dynamic>)?.map((k, e) =>
29+
new MapEntry(
30+
k, (e as List)?.map((e) => e as String)?.toList())) ??
31+
{
32+
'root': ['child']
33+
};
34+
35+
abstract class _$DefaultValueSerializerMixin {
36+
bool get fieldBool;
37+
String get fieldString;
38+
int get fieldInt;
39+
double get fieldDouble;
40+
List<dynamic> get fieldListEmpty;
41+
Map<dynamic, dynamic> get fieldMapEmpty;
42+
List<int> get fieldListSimple;
43+
Map<String, int> get fieldMapSimple;
44+
Map<String, List<String>> get fieldMapListString;
45+
Map<String, dynamic> toJson() => <String, dynamic>{
46+
'fieldBool': fieldBool,
47+
'fieldString': fieldString,
48+
'fieldInt': fieldInt,
49+
'fieldDouble': fieldDouble,
50+
'fieldListEmpty': fieldListEmpty,
51+
'fieldMapEmpty': fieldMapEmpty,
52+
'fieldListSimple': fieldListSimple,
53+
'fieldMapSimple': fieldMapSimple,
54+
'fieldMapListString': fieldMapListString
55+
};
56+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// GENERATED CODE - DO NOT MODIFY BY HAND
6+
7+
// **************************************************************************
8+
// Generator: _NonNullableGenerator
9+
// **************************************************************************
10+
11+
// ignore_for_file: annotate_overrides
12+
13+
import 'package:json_annotation/json_annotation.dart';
14+
15+
part 'default_value.non_nullable.g.dart';
16+
17+
const _intValue = 42;
18+
19+
@JsonSerializable(nullable: false)
20+
class DefaultValue extends Object with _$DefaultValueSerializerMixin {
21+
@JsonKey(defaultValue: true)
22+
bool fieldBool;
23+
24+
@JsonKey(defaultValue: 'string')
25+
String fieldString;
26+
27+
@JsonKey(defaultValue: _intValue)
28+
int fieldInt;
29+
30+
@JsonKey(defaultValue: 3.14)
31+
double fieldDouble;
32+
33+
@JsonKey(defaultValue: [])
34+
List fieldListEmpty;
35+
36+
@JsonKey(defaultValue: {})
37+
Map fieldMapEmpty;
38+
39+
@JsonKey(defaultValue: [1, 2, 3])
40+
List<int> fieldListSimple;
41+
42+
@JsonKey(defaultValue: {'answer': 42})
43+
Map<String, int> fieldMapSimple;
44+
45+
@JsonKey(defaultValue: {
46+
'root': ['child']
47+
})
48+
Map<String, List<String>> fieldMapListString;
49+
50+
DefaultValue();
51+
52+
factory DefaultValue.fromJson(Map<String, dynamic> json) =>
53+
_$DefaultValueFromJson(json);
54+
}

0 commit comments

Comments
 (0)