Skip to content

Cleanup #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/json_serializable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class JsonSerializable {
this.createToJson = createToJson;
}

/// Customizes the how an annotated field is serialized
/// An annotation used to specify how a field is serialized.
class JsonKey {
/// The key in a JSON map to use when reading and writing values corresponding
/// to the annotated fields.
Expand Down
43 changes: 33 additions & 10 deletions lib/src/json_serializable_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,17 @@ class JsonSerializableGenerator

// Sort these in the order in which they appear in the class
// Sadly, `classElement.fields` puts properties after fields
fieldsList.sort((a, b) => a.nameOffset.compareTo(b.nameOffset));
fieldsList.sort((FieldElement a, FieldElement b) {
int offsetFor(FieldElement e) {
if (e.getter != null && e.getter.nameOffset != e.nameOffset) {
assert(e.nameOffset == -1);
return e.getter.nameOffset;
}
return e.nameOffset;
}

return offsetFor(a).compareTo(offsetFor(b));
});

// Explicitly using `LinkedHashMap` – we want these ordered.
var fields = new LinkedHashMap<String, FieldElement>.fromIterable(
Expand Down Expand Up @@ -278,20 +288,33 @@ class JsonSerializableGenerator
/// Returns the JSON map `key` to be used when (de)serializing [field], if any.
///
/// Otherwise, `null`;
String _fieldToJsonMapKey(FieldElement field) =>
_getJsonKeyReader(field)?.read('name')?.anyValue as String;
String _fieldToJsonMapKey(FieldElement field) => _getJsonKeyReader(field).name;

/// Returns `true` if the field should be treated as potentially nullable.
///
/// If no [JsonKey] annotation is present on the field, `true` is returned.
bool _nullable(FieldElement field) =>
_getJsonKeyReader(field)?.read('nullable')?.boolValue ?? true;

ConstantReader _getJsonKeyReader(FieldElement element) {
var obj = _jsonKeyChecker.firstAnnotationOfExact(element) ??
_jsonKeyChecker.firstAnnotationOfExact(element.getter);
bool _nullable(FieldElement field) => _getJsonKeyReader(field).nullable;

JsonKey _getJsonKeyReader(FieldElement element) {
var key = _jsonKeyExpando[element];

if (key == null) {
// If an annotation exists on `element` the source is a "real" field.
// If the result is `null`, check the getter – it is a property.
// TODO(kevmoo) setters: github.com/dart-lang/json_serializable/issues/24
var obj = _jsonKeyChecker.firstAnnotationOfExact(element) ??
_jsonKeyChecker.firstAnnotationOfExact(element.getter);

_jsonKeyExpando[element] = key = obj == null
? const JsonKey()
: new JsonKey(
name: obj.getField('name').toStringValue(),
nullable: obj.getField('nullable').toBoolValue());
}

return obj == null ? null : new ConstantReader(obj);
return key;
}

final _jsonKeyExpando = new Expando<JsonKey>();

final _jsonKeyChecker = new TypeChecker.fromRuntime(JsonKey);
44 changes: 25 additions & 19 deletions test/kitchen_sink_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ void main() {
test('null', () {
var item = new KitchenSink();
roundTripItem(item);

var encoded = item.toJson();
for (var key in _expectedOrder) {
expect(encoded, containsPair(key, isNull));
}
});

test("list and map of DateTime", () {
Expand Down Expand Up @@ -144,24 +149,25 @@ void _sharedTests(

var json = item.toJson();

var expectedOrder = [
'iterable',
'dynamicIterable',
'objectIterable',
'intIterable',
'datetime-iterable',
'list',
'dynamicList',
'objectList',
'intList',
'dateTimeList',
'map',
'stringStringMap',
'stringIntMap',
'stringDateTimeMap',
'crazyComplex'
];

expect(json.keys, orderedEquals(expectedOrder));
expect(json.keys, orderedEquals(_expectedOrder));
});
}

const _expectedOrder = const [
'dateTime',
'iterable',
'dynamicIterable',
'objectIterable',
'intIterable',
'datetime-iterable',
'list',
'dynamicList',
'objectList',
'intList',
'dateTimeList',
'map',
'stringStringMap',
'stringIntMap',
'stringDateTimeMap',
'crazyComplex'
];
3 changes: 3 additions & 0 deletions test/test_files/bathtub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class Bathtub extends Object

factory Bathtub.fromJson(Map<String, Object> json) => _$BathtubFromJson(json);

@JsonKey(nullable: false)
DateTime dateTime = new DateTime(1981, 6, 5);

@JsonKey(nullable: false)
Iterable get iterable => _iterable;
@JsonKey(nullable: false)
Expand Down
3 changes: 3 additions & 0 deletions test/test_files/bathtub.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions test/test_files/kitchen_sink.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class KitchenSink extends Object with _$KitchenSinkSerializerMixin {
factory KitchenSink.fromJson(Map<String, Object> json) =>
_$KitchenSinkFromJson(json);

DateTime dateTime;

Iterable get iterable => _iterable;
Iterable<dynamic> get dynamicIterable => _dynamicIterable;
Iterable<Object> get objectIterable => _objectIterable;
Expand Down Expand Up @@ -71,6 +73,7 @@ class KitchenSink extends Object with _$KitchenSinkSerializerMixin {
//TODO(kevmoo) - finish this...
bool sinkEquals(KitchenSink a, other) =>
other is KitchenSink &&
a.dateTime == other.dateTime &&
_deepEquals(a.iterable, other.iterable) &&
_deepEquals(a.dynamicIterable, other.dynamicIterable) &&
_deepEquals(a.dateTimeIterable, other.dateTimeIterable) &&
Expand Down
10 changes: 7 additions & 3 deletions test/test_files/kitchen_sink.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.