Skip to content

Commit

Permalink
Added createJsonKeys (#1401)
Browse files Browse the repository at this point in the history
Fixes #1400

Co-authored-by: Syméon ROUGEVIN <symeon@oclocher.fr>
Co-authored-by: Kevin Moore <kevmoo@google.com>
  • Loading branch information
3 people authored Mar 3, 2024
1 parent 324acee commit 5b46ef9
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 13 deletions.
4 changes: 3 additions & 1 deletion json_annotation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 4.8.2-wip
## 4.9.0-wip

- Require Dart 3.0
- Added `JsonSerializable(createJsonKeys: true)`.
([#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: 1 addition & 1 deletion json_annotation/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: json_annotation
version: 4.8.2-wip
version: 4.9.0-wip
description: >-
Classes and helper functions that support JSON code generation via the
`json_serializable` package.
Expand Down
4 changes: 3 additions & 1 deletion json_serializable/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 6.7.2-wip
## 6.8.0-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();');

This comment has been minimized.

Copy link
@kevmoo

kevmoo Mar 3, 2024

Author Collaborator

Gah! need to clean this up @ChreSyr !


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
6 changes: 5 additions & 1 deletion json_serializable/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: json_serializable
version: 6.7.2-wip
version: 6.8.0-wip
description: >-
Automatically generate code for converting to and from JSON by annotating
Dart classes.
Expand Down Expand Up @@ -29,6 +29,10 @@ dependencies:
source_gen: ^1.3.2
source_helper: ^1.3.0

dependency_overrides:
json_annotation:
path: ../json_annotation

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;

// 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

0 comments on commit 5b46ef9

Please sign in to comment.