Skip to content

Commit ccf19ee

Browse files
committed
Avoid passing around field + fieldName when field is all you need
Fix one case where we don't properly escape a JSON key with $
1 parent 1afe2b0 commit ccf19ee

File tree

4 files changed

+38
-41
lines changed

4 files changed

+38
-41
lines changed

json_serializable/lib/src/json_serializable_generator.dart

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,20 @@ class JsonSerializableGenerator
124124

125125
// write copies of the fields - this allows the toJson method to access
126126
// the fields of the target class
127-
fields.forEach((name, field) {
127+
for (var field in fields.values) {
128128
//TODO - handle aliased imports
129-
buffer.writeln(' ${field.type} get $name;');
130-
});
129+
buffer.writeln(' ${field.type} get ${field.name};');
130+
}
131131

132132
var includeIfNull = annotation.read('includeIfNull').boolValue;
133133

134134
buffer.writeln(' Map<String, dynamic> toJson() ');
135135
if (fieldsList.every((e) => _includeIfNull(e, includeIfNull))) {
136136
// write simple `toJson` method that includes all keys...
137-
_writeToJsonSimple(buffer, fields);
137+
_writeToJsonSimple(buffer, fields.values);
138138
} else {
139139
// At least one field should be excluded if null
140-
_writeToJsonWithNullChecks(buffer, fields, includeIfNull);
140+
_writeToJsonWithNullChecks(buffer, fields.values, includeIfNull);
141141
}
142142

143143
// end of the mixin class
@@ -147,8 +147,8 @@ class JsonSerializableGenerator
147147
return buffer.toString();
148148
}
149149

150-
void _writeToJsonWithNullChecks(StringBuffer buffer,
151-
Map<String, FieldElement> fields, bool includeIfNull) {
150+
void _writeToJsonWithNullChecks(
151+
StringBuffer buffer, Iterable<FieldElement> fields, bool includeIfNull) {
152152
buffer.writeln('{');
153153

154154
buffer.writeln('var $toJsonMapVarName = <String, dynamic>{');
@@ -159,10 +159,10 @@ class JsonSerializableGenerator
159159
// serialization.
160160
var directWrite = true;
161161

162-
fields.forEach((fieldName, field) {
162+
for (var field in fields) {
163+
var fieldName = field.name;
163164
try {
164-
var safeJsonKeyString =
165-
_safeNameAccess(_fieldToJsonMapKey(field, fieldName));
165+
var safeJsonKeyString = _safeNameAccess(field);
166166

167167
// If `fieldName` collides with one of the local helpers, prefix
168168
// access with `this.`.
@@ -203,29 +203,28 @@ void $toJsonMapHelperName(String key, dynamic value) {
203203
field)}`.',
204204
todo: 'Make sure all of the types are serializable.');
205205
}
206-
});
206+
}
207207

208208
buffer.writeln('return $toJsonMapVarName;');
209209

210210
buffer.writeln('}');
211211
}
212212

213-
void _writeToJsonSimple(
214-
StringBuffer buffer, Map<String, FieldElement> fields) {
213+
void _writeToJsonSimple(StringBuffer buffer, Iterable<FieldElement> fields) {
215214
buffer.writeln('=> <String, dynamic>{');
216215

217216
var pairs = <String>[];
218-
fields.forEach((fieldName, field) {
217+
for (var field in fields) {
219218
try {
220-
pairs.add("'${_fieldToJsonMapKey(field, fieldName)}': "
221-
'${_serialize(field.type, fieldName, _nullable(field))}');
219+
pairs.add('${_safeNameAccess(field)}: '
220+
'${_serialize(field.type, field.name, _nullable(field))}');
222221
} on UnsupportedTypeError {
223222
throw new InvalidGenerationSourceError(
224223
'Could not generate `toJson` code for `${friendlyNameForElement(field)}`.',
225224
todo: 'Make sure all of the types are serializable.');
226225
}
227-
});
228-
buffer.writeAll(pairs, ', ');
226+
}
227+
buffer.writeAll(pairs, ',\n');
229228

230229
buffer.writeln(' };');
231230
}
@@ -303,7 +302,7 @@ void $toJsonMapHelperName(String key, dynamic value) {
303302
buffer.write(' new $className(');
304303
buffer.writeAll(
305304
ctorArguments.map((paramElement) => _deserializeForField(
306-
paramElement.name, fields[paramElement.name],
305+
fields[paramElement.name],
307306
ctorParam: paramElement)),
308307
', ');
309308
if (ctorArguments.isNotEmpty && ctorNamedArguments.isNotEmpty) {
@@ -312,19 +311,19 @@ void $toJsonMapHelperName(String key, dynamic value) {
312311
buffer.writeAll(
313312
ctorNamedArguments.map((paramElement) =>
314313
'${paramElement.name}: ' +
315-
_deserializeForField(paramElement.name, fields[paramElement.name],
314+
_deserializeForField(fields[paramElement.name],
316315
ctorParam: paramElement)),
317316
', ');
318317

319318
buffer.write(')');
320319
if (fieldsToSet.isEmpty) {
321320
buffer.writeln(';');
322321
} else {
323-
fieldsToSet.forEach((name, field) {
322+
for (var field in fieldsToSet.values) {
324323
buffer.writeln();
325-
buffer.write(' ..${name} = ');
326-
buffer.write(_deserializeForField(name, field));
327-
});
324+
buffer.write(' ..${field.name} = ');
325+
buffer.write(_deserializeForField(field));
326+
}
328327
buffer.writeln(';');
329328
}
330329
buffer.writeln();
@@ -344,18 +343,18 @@ void $toJsonMapHelperName(String key, dynamic value) {
344343
orElse: () =>
345344
throw new UnsupportedTypeError(targetType, expression));
346345

347-
String _deserializeForField(String name, FieldElement field,
346+
String _deserializeForField(FieldElement field,
348347
{ParameterElement ctorParam}) {
349-
name = _fieldToJsonMapKey(field, name);
348+
var jsonKey = _safeNameAccess(field);
350349

351350
var targetType = ctorParam?.type ?? field.type;
352351

353352
try {
354-
var safeName = _safeNameAccess(name);
355-
return _deserialize(targetType, 'json[$safeName]', _nullable(field));
353+
return _deserialize(targetType, 'json[$jsonKey]', _nullable(field));
356354
} on UnsupportedTypeError {
357355
throw new InvalidGenerationSourceError(
358-
'Could not generate fromJson code for `${friendlyNameForElement(field)}`.',
356+
'Could not generate fromJson code for '
357+
'`${friendlyNameForElement(field)}`.',
359358
todo: 'Make sure all of the types are serializable.');
360359
}
361360
}
@@ -369,14 +368,11 @@ void $toJsonMapHelperName(String key, dynamic value) {
369368
throw new UnsupportedTypeError(targetType, expression));
370369
}
371370

372-
String _safeNameAccess(String name) =>
373-
name.contains(r'$') ? "r'$name'" : "'$name'";
374-
375-
/// Returns the JSON map `key` to be used when (de)serializing [field], if any.
376-
///
377-
/// Otherwise, `null`;
378-
String _fieldToJsonMapKey(FieldElement field, String ifNull) =>
379-
_jsonKeyFor(field).name ?? ifNull;
371+
String _safeNameAccess(FieldElement field) {
372+
var name = _jsonKeyFor(field).name ?? field.name;
373+
// TODO(kevmoo): JsonKey.name could also have quotes and other silly.
374+
return name.contains(r'$') ? "r'${name}'" : "'${name}'";
375+
}
380376

381377
/// Returns `true` if the field should be treated as potentially nullable.
382378
///

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: 0.2.4+1
2+
version: 0.2.5-dev
33
author: Dart Team <misc@dartlang.org>
44
description: Generates utilities to aid in serializing to/from JSON.
55
homepage: https://github.com/dart-lang/json_serializable

json_serializable/test/test_files/json_test_example.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum House { gryffindor, hufflepuff, ravenclaw, slytherin }
1818
class Person extends Object with _$PersonSerializerMixin {
1919
final String firstName, middleName, lastName;
2020
final DateTime dateOfBirth;
21+
@JsonKey(name: '\$house')
2122
final House house;
2223

2324
Person(this.firstName, this.lastName, this.house,

json_serializable/test/test_files/json_test_example.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.

0 commit comments

Comments
 (0)