Skip to content

Commit

Permalink
feat: Add JsonSerializable(createJsonMeta) (#1164)
Browse files Browse the repository at this point in the history
As discussed before, this adds an option for generating a constant Map of property name: json name

fixes #972
  • Loading branch information
rrousselGit committed Jun 28, 2022
1 parent 0f383e7 commit 25c6138
Show file tree
Hide file tree
Showing 17 changed files with 161 additions and 39 deletions.
2 changes: 2 additions & 0 deletions json_annotation/CHANGELOG.md
@@ -1,5 +1,7 @@
## 4.6.0

- Added `JsonSerializable(createFieldMap: true)`.
([#1164](https://github.com/google/json_serializable.dart/pull/1164))
- Added `JsonSerializable(converters: <JsonConverter>[])`
([#1072](https://github.com/google/json_serializable.dart/issues/1072))

Expand Down
9 changes: 9 additions & 0 deletions json_annotation/lib/src/json_serializable.dart
Expand Up @@ -6,6 +6,7 @@ import 'package:meta/meta_meta.dart';

import 'allowed_keys_helpers.dart';
import 'checked_helpers.dart';
import 'enum_helpers.dart';
import 'json_converter.dart';
import 'json_key.dart';

Expand Down Expand Up @@ -79,6 +80,13 @@ class JsonSerializable {
/// ```
final bool? createFactory;

/// If `true` (defaults to false), a private, static `_$ExampleJsonMeta`
/// constant is created in the generated part file.
///
/// This constant can be used by other code-generators to support features
/// such as [fieldRename].
final bool? createFieldMap;

/// If `true` (the default), A top-level function is created that you can
/// reference from your class.
///
Expand Down Expand Up @@ -231,6 +239,7 @@ class JsonSerializable {
this.anyMap,
this.checked,
this.constructor,
this.createFieldMap,
this.createFactory,
this.createToJson,
this.disallowUnrecognizedKeys,
Expand Down
44 changes: 6 additions & 38 deletions json_annotation/lib/src/json_serializable.g.dart

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

6 changes: 6 additions & 0 deletions json_serializable/CHANGELOG.md
@@ -1,3 +1,9 @@
## 6.3.1-dev

- Added support for generating `_$ExampleFieldMeta`, which can be used by other
code-generators that needs to interact with the JSON serialization.
([#1164](https://github.com/google/json_serializable.dart/pull/1164))

## 6.3.0-dev

- Added support for using a `JsonConverter<MyClass, Object>` on properties
Expand Down
1 change: 1 addition & 0 deletions json_serializable/README.md
Expand Up @@ -179,6 +179,7 @@ targets:
checked: false
constructor: ""
create_factory: true
create_field_map: false
create_to_json: true
disallow_unrecognized_keys: false
explicit_to_json: false
Expand Down
21 changes: 21 additions & 0 deletions json_serializable/lib/src/encoder_helper.dart
Expand Up @@ -16,6 +16,27 @@ import 'unsupported_type_error.dart';
abstract class EncodeHelper implements HelperCore {
String _fieldAccess(FieldElement field) => '$_toJsonParamName.${field.name}';

/// Generates an object containing metadatas related to the encoding,
/// destined to be used by other code-generators.
String createFieldMap(Set<FieldElement> accessibleFieldSet) {
assert(config.createFieldMap);

final buffer = StringBuffer(
'const _\$${element.name.nonPrivate}FieldMap = <String, String> {',
);

for (final field in accessibleFieldSet) {
buffer.writeln(
'${escapeDartString(field.name)}: '
'${escapeDartString(nameAccess(field))},',
);
}

buffer.write('};');

return buffer.toString();
}

Iterable<String> createToJson(Set<FieldElement> accessibleFields) sync* {
assert(config.createToJson);

Expand Down
4 changes: 4 additions & 0 deletions json_serializable/lib/src/generator_helper.dart
Expand Up @@ -108,6 +108,10 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
},
);

if (config.createFieldMap) {
yield createFieldMap(accessibleFieldSet);
}

if (config.createToJson) {
yield* createToJson(accessibleFieldSet);
}
Expand Down
6 changes: 6 additions & 0 deletions json_serializable/lib/src/type_helpers/config_types.dart
Expand Up @@ -45,6 +45,7 @@ class ClassConfig {
final String constructor;
final bool createFactory;
final bool createToJson;
final bool createFieldMap;
final bool disallowUnrecognizedKeys;
final bool explicitToJson;
final FieldRename fieldRename;
Expand All @@ -60,6 +61,7 @@ class ClassConfig {
required this.constructor,
required this.createFactory,
required this.createToJson,
required this.createFieldMap,
required this.disallowUnrecognizedKeys,
required this.explicitToJson,
required this.fieldRename,
Expand All @@ -76,6 +78,8 @@ class ClassConfig {
checked: config.checked ?? ClassConfig.defaults.checked,
anyMap: config.anyMap ?? ClassConfig.defaults.anyMap,
constructor: config.constructor ?? ClassConfig.defaults.constructor,
createFieldMap:
config.createFieldMap ?? ClassConfig.defaults.createFieldMap,
createFactory:
config.createFactory ?? ClassConfig.defaults.createFactory,
createToJson: config.createToJson ?? ClassConfig.defaults.createToJson,
Expand All @@ -101,6 +105,7 @@ class ClassConfig {
constructor: '',
createFactory: true,
createToJson: true,
createFieldMap: false,
disallowUnrecognizedKeys: false,
explicitToJson: false,
fieldRename: FieldRename.none,
Expand All @@ -115,6 +120,7 @@ class ClassConfig {
constructor: constructor,
createFactory: createFactory,
createToJson: createToJson,
createFieldMap: createFieldMap,
ignoreUnannotated: ignoreUnannotated,
explicitToJson: explicitToJson,
includeIfNull: includeIfNull,
Expand Down
2 changes: 2 additions & 0 deletions json_serializable/lib/src/utils.dart
Expand Up @@ -56,6 +56,7 @@ JsonSerializable _valueForAnnotation(ConstantReader reader) => JsonSerializable(
constructor: reader.read('constructor').literalValue as String?,
createFactory: reader.read('createFactory').literalValue as bool?,
createToJson: reader.read('createToJson').literalValue as bool?,
createFieldMap: reader.read('createFieldMap').literalValue as bool?,
disallowUnrecognizedKeys:
reader.read('disallowUnrecognizedKeys').literalValue as bool?,
explicitToJson: reader.read('explicitToJson').literalValue as bool?,
Expand Down Expand Up @@ -101,6 +102,7 @@ ClassConfig mergeConfig(
constructor: constructor,
createFactory: annotation.createFactory ?? config.createFactory,
createToJson: annotation.createToJson ?? config.createToJson,
createFieldMap: annotation.createFieldMap ?? config.createFieldMap,
disallowUnrecognizedKeys:
annotation.disallowUnrecognizedKeys ?? config.disallowUnrecognizedKeys,
explicitToJson: annotation.explicitToJson ?? config.explicitToJson,
Expand Down
2 changes: 1 addition & 1 deletion json_serializable/pubspec.yaml
@@ -1,5 +1,5 @@
name: json_serializable
version: 6.3.0-dev
version: 6.3.1-dev
description: >-
Automatically generate code for converting to and from JSON by annotating
Dart classes.
Expand Down
5 changes: 5 additions & 0 deletions json_serializable/test/config_test.dart
Expand Up @@ -126,6 +126,10 @@ void main() {
lastLine = "type 'int' is not a subtype of type 'String?' in type "
'cast';
break;
case 'create_to_json':
lastLine = "type 'int' is not a subtype of type 'bool?' in type "
'cast';
break;
default:
lastLine =
"type 'int' is not a subtype of type 'bool?' in type cast";
Expand All @@ -152,6 +156,7 @@ const _invalidConfig = {
'checked': 42,
'constructor': 42,
'create_factory': 42,
'create_field_map': 42,
'create_to_json': 42,
'disallow_unrecognized_keys': 42,
'explicit_to_json': 42,
Expand Down
43 changes: 43 additions & 0 deletions json_serializable/test/integration/field_map_example.dart
@@ -0,0 +1,43 @@
import 'package:json_annotation/json_annotation.dart';

part 'field_map_example.g.dart';

@JsonSerializable(createFieldMap: true, fieldRename: FieldRename.kebab)
class Model {
Model({
required this.firstName,
required this.lastName,
this.ignoredName,
});

factory Model.fromJson(Map<String, Object?> json) => _$ModelFromJson(json);

final String firstName;

@JsonKey(name: 'LAST_NAME')
final String lastName;

@JsonKey(ignore: true)
final String? ignoredName;

String get fullName => '$firstName $lastName';

Map<String, Object?> toJson() => _$ModelToJson(this);
}

const modelFieldMap = _$ModelFieldMap;

@JsonSerializable(
createFieldMap: true,
fieldRename: FieldRename.kebab,
createFactory: false,
)
class _PrivateModel {
_PrivateModel(this.fullName);

final String fullName;

Map<String, Object?> toJson() => _$PrivateModelToJson(this);
}

const privateModelFieldMap = _$PrivateModelFieldMap;
33 changes: 33 additions & 0 deletions json_serializable/test/integration/field_map_example.g.dart

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

19 changes: 19 additions & 0 deletions json_serializable/test/integration/integration_test.dart
Expand Up @@ -6,6 +6,7 @@ import 'package:json_annotation/json_annotation.dart';
import 'package:test/test.dart';

import '../test_utils.dart';
import 'field_map_example.dart';
import 'json_enum_example.dart';
import 'json_test_common.dart' show Category, Platform, StatusCode;
import 'json_test_example.dart';
Expand Down Expand Up @@ -339,4 +340,22 @@ void main() {
isNull,
);
});

test(r'_$ModelFieldMap', () {
expect(
modelFieldMap,
{
'firstName': 'first-name',
'lastName': 'LAST_NAME',
},
);
});

test(r'Generates _$PrivateModelFieldMap instead of __$PrivateModelFieldMap',
() {
expect(
privateModelFieldMap,
{'fullName': 'full-name'},
);
});
}
1 change: 1 addition & 0 deletions json_serializable/test/shared_config.dart
Expand Up @@ -19,6 +19,7 @@ final generatorConfigNonDefaultJson =
constructor: 'something',
createFactory: false,
createToJson: false,
createFieldMap: true,
disallowUnrecognizedKeys: true,
explicitToJson: true,
fieldRename: FieldRename.kebab,
Expand Down
1 change: 1 addition & 0 deletions json_serializable/test/test_sources/test_sources.dart
Expand Up @@ -15,6 +15,7 @@ class ConfigurationImplicitDefaults {
constructor: '',
createFactory: true,
createToJson: true,
createFieldMap: false,
disallowUnrecognizedKeys: false,
explicitToJson: false,
fieldRename: FieldRename.none,
Expand Down
1 change: 1 addition & 0 deletions json_serializable/tool/readme/readme_template.md
Expand Up @@ -137,6 +137,7 @@ targets:
checked: false
constructor: ""
create_factory: true
create_field_map: false
create_to_json: true
disallow_unrecognized_keys: false
explicit_to_json: false
Expand Down

0 comments on commit 25c6138

Please sign in to comment.