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

Added createJsonKeys #1401

Merged
merged 13 commits into from
Mar 3, 2024
2 changes: 2 additions & 0 deletions json_annotation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 4.8.2-wip

- Require Dart 3.0
- Added `JsonSerializable(createJsonKeys: true)`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 4.9.0 since we're adding new features!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto with json_serial. I'll do it. Just FYI for future.

([#1401](https://github.com/google/json_serializable.dart/pull/1401))

## 4.8.1

Expand Down
16 changes: 16 additions & 0 deletions json_annotation/lib/src/json_serializable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ class JsonSerializable {
/// such as [fieldRename].
final bool? createFieldMap;

/// If `true` (defaults to false), a private class `_$ExampleJsonKeys`
/// constant is created in the generated part file.
///
/// This class will contain every property, with the json key as value,
/// exposing a secured way to access the json key from the property.
///
/// ```dart
/// @JsonSerializable(createJsonKeys: true)
/// class Example {
/// // ...
/// static const jsonKeys = _$PublicationImplJsonKeys();
/// }
/// ```
final bool? createJsonKeys;

/// If `true` (defaults to false), a private, static `_$ExamplePerFieldToJson`
/// abstract class will be generated in the part file.
///
Expand Down Expand Up @@ -247,6 +262,7 @@ class JsonSerializable {
this.checked,
this.constructor,
this.createFieldMap,
this.createJsonKeys,
this.createFactory,
this.createToJson,
this.disallowUnrecognizedKeys,
Expand Down
5 changes: 5 additions & 0 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.

2 changes: 2 additions & 0 deletions json_serializable/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 6.7.2-wip

- Add type arguments to `Map` literals used for `Record` serialization.
- Added support for generating `ExampleJsonKeys`, exposing a secured way to access the json keys from the properties.
([#1164](https://github.com/google/json_serializable.dart/pull/1164))

## 6.7.1

Expand Down
19 changes: 10 additions & 9 deletions json_serializable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ targets:
constructor: ""
create_factory: true
create_field_map: false
create_json_keys: false
create_per_field_to_json: false
create_to_json: true
disallow_unrecognized_keys: false
Expand All @@ -297,15 +298,15 @@ 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.8.1/json_annotation/JsonConverter-class.html
[`JsonEnum.valueField`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonEnum/valueField.html
[`JsonEnum`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonEnum-class.html
[`JsonKey.fromJson`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonKey/fromJson.html
[`JsonKey.toJson`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonKey/toJson.html
[`JsonKey`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonKey-class.html
[`JsonLiteral`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonLiteral-class.html
[`JsonSerializable`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonSerializable-class.html
[`JsonValue`]: https://pub.dev/documentation/json_annotation/4.8.1/json_annotation/JsonValue-class.html
[`JsonConverter`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
[`JsonEnum.valueField`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonEnum/valueField.html
[`JsonEnum`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonEnum-class.html
[`JsonKey.fromJson`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
[`JsonKey.toJson`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
[`JsonKey`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey-class.html
[`JsonLiteral`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonLiteral-class.html
[`JsonSerializable`]: https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable-class.html
[`JsonValue`]: https://pub.dev/documentation/json_annotation/latest/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
22 changes: 22 additions & 0 deletions json_serializable/lib/src/encoder_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ mixin EncodeHelper implements HelperCore {
return buffer.toString();
}

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

final buffer = StringBuffer(
'abstract final class _\$${element.name.nonPrivate}JsonKeys {',
);
// ..write('static const _\$${element.name.nonPrivate}JsonKeys();');

for (final field in accessibleFieldSet) {
buffer.writeln(
'static const String ${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
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
yield createFieldMap(accessibleFieldSet);
}

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

if (config.createPerFieldToJson) {
yield createPerFieldToJson(accessibleFieldSet);
}
Expand Down
6 changes: 6 additions & 0 deletions json_serializable/lib/src/type_helpers/config_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ClassConfig {
final bool createFactory;
final bool createToJson;
final bool createFieldMap;
final bool createJsonKeys;
final bool createPerFieldToJson;
final bool disallowUnrecognizedKeys;
final bool explicitToJson;
Expand All @@ -66,6 +67,7 @@ class ClassConfig {
required this.createFactory,
required this.createToJson,
required this.createFieldMap,
required this.createJsonKeys,
required this.createPerFieldToJson,
required this.disallowUnrecognizedKeys,
required this.explicitToJson,
Expand All @@ -85,6 +87,8 @@ class ClassConfig {
constructor: config.constructor ?? ClassConfig.defaults.constructor,
createFieldMap:
config.createFieldMap ?? ClassConfig.defaults.createFieldMap,
createJsonKeys:
config.createJsonKeys ?? ClassConfig.defaults.createJsonKeys,
createPerFieldToJson: config.createPerFieldToJson ??
ClassConfig.defaults.createPerFieldToJson,
createFactory:
Expand Down Expand Up @@ -113,6 +117,7 @@ class ClassConfig {
createFactory: true,
createToJson: true,
createFieldMap: false,
createJsonKeys: false,
createPerFieldToJson: false,
disallowUnrecognizedKeys: false,
explicitToJson: false,
Expand All @@ -129,6 +134,7 @@ class ClassConfig {
createFactory: createFactory,
createToJson: createToJson,
createFieldMap: createFieldMap,
createJsonKeys: createJsonKeys,
createPerFieldToJson: createPerFieldToJson,
ignoreUnannotated: ignoreUnannotated,
explicitToJson: explicitToJson,
Expand Down
2 changes: 2 additions & 0 deletions json_serializable/lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ JsonSerializable _valueForAnnotation(ConstantReader reader) => JsonSerializable(
createFactory: reader.read('createFactory').literalValue as bool?,
createToJson: reader.read('createToJson').literalValue as bool?,
createFieldMap: reader.read('createFieldMap').literalValue as bool?,
createJsonKeys: reader.read('createJsonKeys').literalValue as bool?,
createPerFieldToJson:
reader.read('createPerFieldToJson').literalValue as bool?,
disallowUnrecognizedKeys:
Expand Down Expand Up @@ -106,6 +107,7 @@ ClassConfig mergeConfig(
createFactory: annotation.createFactory ?? config.createFactory,
createToJson: annotation.createToJson ?? config.createToJson,
createFieldMap: annotation.createFieldMap ?? config.createFieldMap,
createJsonKeys: annotation.createJsonKeys ?? config.createJsonKeys,
createPerFieldToJson:
annotation.createPerFieldToJson ?? config.createPerFieldToJson,
disallowUnrecognizedKeys:
Expand Down
4 changes: 4 additions & 0 deletions json_serializable/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ dependencies:
source_gen: ^1.3.2
source_helper: ^1.3.0

dependency_overrides:
json_annotation:
path: ../json_annotation

kevmoo marked this conversation as resolved.
Show resolved Hide resolved
dev_dependencies:
_json_serial_shared_test:
path: ../shared_test
Expand Down
1 change: 1 addition & 0 deletions json_serializable/test/config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ const _invalidConfig = {
'constructor': 42,
'create_factory': 42,
'create_field_map': 42,
'create_json_keys': 42,
'create_per_field_to_json': 42,
'create_to_json': 42,
'disallow_unrecognized_keys': 42,
Expand Down
5 changes: 5 additions & 0 deletions json_serializable/test/integration/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'converter_examples.dart';
import 'create_per_field_to_json_example.dart';
import 'field_map_example.dart';
import 'json_enum_example.dart';
import 'json_keys_example.dart' as js_keys;
import 'json_test_common.dart' show Category, Platform, StatusCode;
import 'json_test_example.dart';

Expand Down Expand Up @@ -471,4 +472,8 @@ void main() {
test('value field index fun', () {
expect(enumValueFieldIndexValues, [0, 701, 2]);
});

test('ModelJsonKeys', () {
expect(js_keys.keys, {'first-name', 'LAST_NAME'});
});
}
32 changes: 32 additions & 0 deletions json_serializable/test/integration/json_keys_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:json_annotation/json_annotation.dart';

part 'json_keys_example.g.dart';

@JsonSerializable(createJsonKeys: 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(includeFromJson: false, includeToJson: false)
final String? ignoredName;

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

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

// TODO: use this once https://github.com/dart-lang/sdk/issues/54543 is fixed
typedef ModelJsonKeys = _$ModelJsonKeys;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart, i like the idea

Copy link

@Juliotati Juliotati Apr 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ChreSyr would be really nice to have this auto generated inside json_keys_example.g.dart above the generated ModelJsonKeys class


// Work-around until https://github.com/dart-lang/sdk/issues/54543 is fixed
Set<String> get keys => {_$ModelJsonKeys.firstName, _$ModelJsonKeys.lastName};
24 changes: 24 additions & 0 deletions json_serializable/test/integration/json_keys_example.g.dart

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

1 change: 1 addition & 0 deletions json_serializable/test/shared_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ final generatorConfigNonDefaultJson =
createFactory: false,
createToJson: false,
createFieldMap: true,
createJsonKeys: true,
createPerFieldToJson: true,
disallowUnrecognizedKeys: true,
explicitToJson: true,
Expand Down
1 change: 1 addition & 0 deletions json_serializable/test/test_sources/test_sources.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ConfigurationImplicitDefaults {
createFactory: true,
createToJson: true,
createFieldMap: false,
createJsonKeys: false,
createPerFieldToJson: false,
disallowUnrecognizedKeys: false,
explicitToJson: false,
Expand Down
1 change: 1 addition & 0 deletions json_serializable/tool/readme/readme_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ targets:
constructor: ""
create_factory: true
create_field_map: false
create_json_keys: false
create_per_field_to_json: false
create_to_json: true
disallow_unrecognized_keys: false
Expand Down