Skip to content
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

feat: Add JsonSerializable(createJsonMeta) #1164

Merged
merged 16 commits into from Jun 28, 2022
Merged
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.

7 changes: 4 additions & 3 deletions json_annotation/pubspec.yaml
Expand Up @@ -12,6 +12,7 @@ dependencies:
meta: ^1.4.0

# When changing JsonSerializable class.
# dev_dependencies:
# build_runner: ^2.0.0
# json_serializable: any
dev_dependencies:
rrousselGit marked this conversation as resolved.
Show resolved Hide resolved
build_runner: ^2.0.0
json_serializable:
path: ../json_serializable
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
17 changes: 9 additions & 8 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 All @@ -199,14 +200,14 @@ targets:
[`Enum`]: https://api.dart.dev/stable/dart-core/Enum-class.html
[`int`]: https://api.dart.dev/stable/dart-core/int-class.html
[`Iterable`]: https://api.dart.dev/stable/dart-core/Iterable-class.html
[`JsonConverter`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonConverter-class.html
[`JsonEnum`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonEnum-class.html
[`JsonKey.fromJson`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonKey/fromJson.html
[`JsonKey.toJson`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonKey/toJson.html
[`JsonKey`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonKey-class.html
[`JsonLiteral`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonLiteral-class.html
[`JsonSerializable`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonSerializable-class.html
[`JsonValue`]: https://pub.dev/documentation/json_annotation/4.6.0/json_annotation/JsonValue-class.html
[`JsonConverter`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonConverter-class.html
[`JsonEnum`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonEnum-class.html
[`JsonKey.fromJson`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonKey/fromJson.html
[`JsonKey.toJson`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonKey/toJson.html
[`JsonKey`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonKey-class.html
[`JsonLiteral`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonLiteral-class.html
[`JsonSerializable`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonSerializable-class.html
[`JsonValue`]: https://pub.dev/documentation/json_annotation/4.5.0/json_annotation/JsonValue-class.html
[`List`]: https://api.dart.dev/stable/dart-core/List-class.html
[`Map`]: https://api.dart.dev/stable/dart-core/Map-class.html
[`num`]: https://api.dart.dev/stable/dart-core/num-class.html
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.