Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions json_annotation/lib/src/json_serializable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ class JsonSerializable {
/// fields annotated with [JsonKey].
final FieldRename? fieldRename;

/// Default field rename for enum values when not set on [JsonEnum].
///
/// Only applies when configured via `build.yaml`; has no effect when set on
/// [JsonSerializable] annotations in source code.
final FieldRename? enumFieldRename;

/// When `true` on classes with type parameters (generic types), extra
/// "helper" parameters will be generated for `fromJson` and/or `toJson` to
/// support serializing values of those types.
Expand Down Expand Up @@ -278,6 +284,7 @@ class JsonSerializable {
this.disallowUnrecognizedKeys,
this.explicitToJson,
this.fieldRename,
this.enumFieldRename,
this.ignoreUnannotated,
this.includeIfNull,
this.converters,
Expand All @@ -300,6 +307,7 @@ class JsonSerializable {
disallowUnrecognizedKeys: false,
explicitToJson: false,
fieldRename: FieldRename.none,
enumFieldRename: FieldRename.none,
ignoreUnannotated: false,
includeIfNull: true,
genericArgumentFactories: false,
Expand All @@ -321,6 +329,7 @@ class JsonSerializable {
disallowUnrecognizedKeys ?? defaults.disallowUnrecognizedKeys,
explicitToJson: explicitToJson ?? defaults.explicitToJson,
fieldRename: fieldRename ?? defaults.fieldRename,
enumFieldRename: enumFieldRename ?? defaults.enumFieldRename,
ignoreUnannotated: ignoreUnannotated ?? defaults.ignoreUnannotated,
includeIfNull: includeIfNull ?? defaults.includeIfNull,
genericArgumentFactories:
Expand Down
7 changes: 7 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.

1 change: 1 addition & 0 deletions json_serializable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ targets:
create_to_json: true
disallow_unrecognized_keys: false
explicit_to_json: false
enum_field_rename: none
field_rename: none
generic_argument_factories: false
ignore_unannotated: false
Expand Down
5 changes: 4 additions & 1 deletion json_serializable/lib/src/encoder_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ mixin EncodeHelper implements HelperCore {
// We can consider enums as kinda like having custom converters
// same rules apply. If `null` is in the set of encoded values, we
// should not write naive
final enumWithNullValue = enumFieldWithNullInEncodeMap(field.type);
final enumWithNullValue = enumFieldWithNullInEncodeMap(
field.type,
defaultEnumFieldRename: config.enumFieldRename,
);
if (enumWithNullValue != null) {
return !enumWithNullValue;
}
Expand Down
22 changes: 17 additions & 5 deletions json_serializable/lib/src/enum_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ String constMapName(DartType targetType) =>
///
/// Otherwise, returns `true` if [targetType] is nullable OR if one of the
/// encoded values of the enum is `null`.
bool? enumFieldWithNullInEncodeMap(DartType targetType) {
final enumMap = _enumMap(targetType);
bool? enumFieldWithNullInEncodeMap(
DartType targetType, {
FieldRename? defaultEnumFieldRename,
}) {
final enumMap = _enumMap(
targetType,
defaultEnumFieldRename: defaultEnumFieldRename,
);

if (enumMap == null) return null;

Expand All @@ -34,10 +40,12 @@ bool? enumFieldWithNullInEncodeMap(DartType targetType) {
String? enumValueMapFromType(
DartType targetType, {
bool nullWithNoAnnotation = false,
FieldRename? defaultEnumFieldRename,
}) {
final enumMap = _enumMap(
targetType,
nullWithNoAnnotation: nullWithNoAnnotation,
defaultEnumFieldRename: defaultEnumFieldRename,
);

if (enumMap == null) return null;
Expand All @@ -56,6 +64,7 @@ String? enumValueMapFromType(
Map<FieldElement, Object?>? _enumMap(
DartType targetType, {
bool nullWithNoAnnotation = false,
FieldRename? defaultEnumFieldRename,
}) {
final targetTypeElement = targetType.element;
if (targetTypeElement == null) return null;
Expand All @@ -74,6 +83,7 @@ Map<FieldElement, Object?>? _enumMap(
field: field,
jsonEnum: jsonEnum,
targetType: targetType,
defaultEnumFieldRename: defaultEnumFieldRename,
),
};
}
Expand All @@ -82,6 +92,7 @@ Object? _generateEntry({
required FieldElement field,
required JsonEnum jsonEnum,
required DartType targetType,
FieldRename? defaultEnumFieldRename,
}) {
final annotation = const TypeChecker.typeNamed(
JsonValue,
Expand All @@ -91,8 +102,6 @@ Object? _generateEntry({
if (annotation == null) {
final valueField = jsonEnum.valueField;
if (valueField != null) {
// TODO: fieldRename is pointless here!!! At least log a warning!

final fieldElementType = field.type.element as EnumElement;

final e = fieldElementType.getField(valueField);
Expand Down Expand Up @@ -125,7 +134,10 @@ Object? _generateEntry({
);
}
} else {
return encodedFieldName(jsonEnum.fieldRename, field.name!);
final effectiveRename = jsonEnum.fieldRename != FieldRename.none
? jsonEnum.fieldRename
: (defaultEnumFieldRename ?? FieldRename.none);
return encodedFieldName(effectiveRename, field.name!);
}
} else {
final reader = ConstantReader(annotation);
Expand Down
6 changes: 5 additions & 1 deletion json_serializable/lib/src/json_enum_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import 'package:json_annotation/json_annotation.dart';
import 'package:source_gen/source_gen.dart';

import 'enum_utils.dart';
import 'settings.dart';

class JsonEnumGenerator extends GeneratorForAnnotation<JsonEnum> {
const JsonEnumGenerator() : super(inPackage: 'json_annotation');
JsonEnumGenerator(this._settings) : super(inPackage: 'json_annotation');

final Settings _settings;

@override
List<String> generateForAnnotatedElement(
Expand All @@ -28,6 +31,7 @@ class JsonEnumGenerator extends GeneratorForAnnotation<JsonEnum> {
final value = enumValueMapFromType(
element.thisType,
nullWithNoAnnotation: true,
defaultEnumFieldRename: _settings.config.enumFieldRename,
);

return [?value];
Expand Down
2 changes: 1 addition & 1 deletion json_serializable/lib/src/json_part_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Builder jsonPartBuilder({
[
_UnifiedGenerator([
JsonSerializableGenerator.fromSettings(settings),
const JsonEnumGenerator(),
JsonEnumGenerator(settings),
]),
const JsonLiteralGenerator(),
],
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 @@ -64,6 +64,7 @@ class ClassConfig {
final bool disallowUnrecognizedKeys;
final bool explicitToJson;
final FieldRename fieldRename;
final FieldRename enumFieldRename;
final bool genericArgumentFactories;
final bool ignoreUnannotated;
final bool includeIfNull;
Expand All @@ -83,6 +84,7 @@ class ClassConfig {
required this.disallowUnrecognizedKeys,
required this.explicitToJson,
required this.fieldRename,
required this.enumFieldRename,
required this.genericArgumentFactories,
required this.ignoreUnannotated,
required this.includeIfNull,
Expand Down Expand Up @@ -118,6 +120,8 @@ class ClassConfig {
config.genericArgumentFactories ??
ClassConfig.defaults.genericArgumentFactories,
fieldRename: config.fieldRename ?? ClassConfig.defaults.fieldRename,
enumFieldRename:
config.enumFieldRename ?? ClassConfig.defaults.enumFieldRename,
disallowUnrecognizedKeys:
config.disallowUnrecognizedKeys ??
ClassConfig.defaults.disallowUnrecognizedKeys,
Expand All @@ -139,6 +143,7 @@ class ClassConfig {
disallowUnrecognizedKeys: false,
explicitToJson: false,
fieldRename: FieldRename.none,
enumFieldRename: FieldRename.none,
genericArgumentFactories: false,
ignoreUnannotated: false,
includeIfNull: true,
Expand All @@ -159,6 +164,7 @@ class ClassConfig {
includeIfNull: includeIfNull,
genericArgumentFactories: genericArgumentFactories,
fieldRename: fieldRename,
enumFieldRename: enumFieldRename,
disallowUnrecognizedKeys: disallowUnrecognizedKeys,
// TODO typeConverters = []
);
Expand Down
15 changes: 12 additions & 3 deletions json_serializable/lib/src/type_helpers/enum_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ class EnumHelper extends TypeHelper<TypeHelperContextWithConfig> {
String expression,
TypeHelperContextWithConfig context,
) {
final memberContent = enumValueMapFromType(targetType);
final memberContent = enumValueMapFromType(
targetType,
defaultEnumFieldRename: context.config.enumFieldRename,
);

if (memberContent == null) {
return null;
Expand All @@ -30,7 +33,10 @@ class EnumHelper extends TypeHelper<TypeHelperContextWithConfig> {
context.addMember(memberContent);

if (targetType.isNullableType ||
enumFieldWithNullInEncodeMap(targetType) == true) {
enumFieldWithNullInEncodeMap(
targetType,
defaultEnumFieldRename: context.config.enumFieldRename,
) == true) {
return '${constMapName(targetType)}[$expression]';
} else {
return '${constMapName(targetType)}[$expression]!';
Expand All @@ -44,7 +50,10 @@ class EnumHelper extends TypeHelper<TypeHelperContextWithConfig> {
TypeHelperContextWithConfig context,
bool defaultProvided,
) {
final memberContent = enumValueMapFromType(targetType);
final memberContent = enumValueMapFromType(
targetType,
defaultEnumFieldRename: context.config.enumFieldRename,
);

if (memberContent == null) {
return null;
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 @@ -70,6 +70,7 @@ JsonSerializable _valueForAnnotation(ConstantReader reader) => JsonSerializable(
reader.read('disallowUnrecognizedKeys').literalValue as bool?,
explicitToJson: reader.read('explicitToJson').literalValue as bool?,
fieldRename: readEnum(reader.read('fieldRename'), FieldRename.values),
enumFieldRename: readEnum(reader.read('enumFieldRename'), FieldRename.values),
genericArgumentFactories:
reader.read('genericArgumentFactories').literalValue as bool?,
ignoreUnannotated: reader.read('ignoreUnannotated').literalValue as bool?,
Expand Down Expand Up @@ -120,6 +121,7 @@ ClassConfig mergeConfig(
annotation.disallowUnrecognizedKeys ?? config.disallowUnrecognizedKeys,
explicitToJson: annotation.explicitToJson ?? config.explicitToJson,
fieldRename: annotation.fieldRename ?? config.fieldRename,
enumFieldRename: annotation.enumFieldRename ?? config.enumFieldRename,
genericArgumentFactories:
annotation.genericArgumentFactories ??
(classElement.typeParameters.isNotEmpty &&
Expand Down
4 changes: 4 additions & 0 deletions json_serializable/test/config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ void main() {

String lastLine;
lastLine = switch (entry.key) {
'enum_field_rename' =>
'`42` is not one of the supported values: none, kebab, snake, '
'pascal, screamingSnake',
'field_rename' =>
'`42` is not one of the supported values: none, kebab, snake, '
'pascal, screamingSnake',
Expand Down Expand Up @@ -177,6 +180,7 @@ const _invalidConfig = {
'create_per_field_to_json': 42,
'create_to_json': 42,
'disallow_unrecognized_keys': 42,
'enum_field_rename': 42,
'explicit_to_json': 42,
'field_rename': 42,
'generic_argument_factories': 42,
Expand Down
3 changes: 2 additions & 1 deletion json_serializable/test/json_serializable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
library;

import 'package:json_serializable/json_serializable.dart';
import 'package:json_serializable/src/settings.dart';
import 'package:path/path.dart' as p;
import 'package:source_gen_test/source_gen_test.dart';
import 'package:test/test.dart';
Expand Down Expand Up @@ -41,7 +42,7 @@ Future<void> main() async {

testAnnotatedElements(
jsonEnumTestReader,
const JsonEnumGenerator(),
JsonEnumGenerator(Settings()),
expectedAnnotatedTests: {
'EnumValueIssue1147',
'EnumValueNotAField',
Expand Down
1 change: 1 addition & 0 deletions json_serializable/test/shared_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final generatorConfigNonDefaultJson = Map<String, dynamic>.unmodifiable(
createPerFieldToJson: true,
disallowUnrecognizedKeys: true,
explicitToJson: true,
enumFieldRename: FieldRename.pascal,
fieldRename: FieldRename.kebab,
ignoreUnannotated: true,
includeIfNull: false,
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 @@ -19,6 +19,7 @@ class ConfigurationImplicitDefaults {
createJsonKeys: false,
createPerFieldToJson: false,
disallowUnrecognizedKeys: false,
enumFieldRename: FieldRename.none,
explicitToJson: false,
fieldRename: FieldRename.none,
ignoreUnannotated: 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 @@ -178,6 +178,7 @@ targets:
create_to_json: true
disallow_unrecognized_keys: false
explicit_to_json: false
enum_field_rename: none
field_rename: none
generic_argument_factories: false
ignore_unannotated: false
Expand Down
Loading