Skip to content

Add enum_field_rename option in build.yaml for default enum value renaming#1556

Open
jlalvarez18 wants to merge 20 commits intogoogle:masterfrom
jlalvarez18:enum-serializer-opt-48194
Open

Add enum_field_rename option in build.yaml for default enum value renaming#1556
jlalvarez18 wants to merge 20 commits intogoogle:masterfrom
jlalvarez18:enum-serializer-opt-48194

Conversation

@jlalvarez18
Copy link

Summary

Adds an enum_field_rename option to the json_serializable builder config so packages can set a default field-rename strategy for enum values (e.g. PascalCase from the backend) without annotating every enum with @JsonEnum(fieldRename: ...).

Fixes #1021.

Problem

field_rename in build.yaml only affects class fields, not enum value names. Enums had to set @JsonEnum(fieldRename: ...) on each type. There was no way to configure a package-wide default for enum value renaming.

Solution

Introduce a separate option enum_field_rename in the build config. When generating enum value maps:

  • If @JsonEnum(fieldRename: ...) is set to something other than none, that value is used.
  • Otherwise, the build config enum_field_rename is used (default none).

Changes

json_annotation

  • Added optional enumFieldRename to JsonSerializable (used when parsing build.yaml).
  • Updated generated json_serializable.g.dart for fromJson/toJson and allowed keys.

json_serializable

  • ClassConfig: Added enumFieldRename (default FieldRename.none) and wired it from JsonSerializable and in mergeConfig.
  • enum_utils: enumValueMapFromType (and helpers) accept optional defaultEnumFieldRename; effective rename is annotation value if non-none, else config default, else none.
  • JsonEnumGenerator: Takes Settings and passes config.enumFieldRename as the default for enums.
  • EnumHelper / encoder_helper: Pass context.config.enumFieldRename (or config.enumFieldRename) into enum helpers so the default is applied when encoding/decoding enum fields.

Examples

1. build.yaml – default PascalCase for all enums

targets:
  $default:
    builders:
      json_serializable:
        options:
          enum_field_rename: pascal

Enums without @JsonEnum(fieldRename: ...) (or with fieldRename: none) will serialize with PascalCase:

// No per-enum annotation needed
enum Status { active, pending, completed }

// Serializes as: "Active", "Pending", "Completed"

2. Per-enum override

@JsonEnum(fieldRename: FieldRename.snake)
enum ApiStatus { active, pending }

// Uses snake_case: "active", "pending" (annotation overrides build config)

3. Same options as other build config

targets:
  $default:
    builders:
      json_serializable:
        options:
          field_rename: snake        # class fields → snake_case
          enum_field_rename: pascal   # enum values → PascalCase

4. Supported values

Same as field_rename: none, kebab, snake, pascal, screamingSnake.

Documentation

  • README.md and tool/readme/readme_template.md: Document enum_field_rename: none in the build configuration options.
  • In YAML use snake_case (enum_field_rename); in Dart use camelCase (enumFieldRename), consistent with field_rename / fieldRename.

Testing

  • config_test.dart: enum_field_rename in default config, invalid config handling, and key ordering.
  • shared_config.dart: Non-default enumFieldRename in generatorConfigNonDefaultJson.
  • test_sources.dart: ConfigurationExplicitDefaults includes enumFieldRename: FieldRename.none so annotation-over-config behavior is tested.
  • json_serializable_test.dart: JsonEnumGenerator updated to use JsonEnumGenerator(Settings()) so enum generation uses the new default.

All existing tests pass (624 tests).

fixes #1021

- Introduced `enumFieldRename` property to `JsonSerializable` for default field renaming of enum values.
- Updated serialization and deserialization methods to handle the new `enumFieldRename` field.
- Modified README to document the new configuration option.
- Adjusted encoding logic to utilize the `enumFieldRename` setting when processing enums.
@gemini-code-assist
Copy link

Summary of Changes

Hello @jlalvarez18, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the json_serializable package by introducing a new configuration option, enum_field_rename, which allows developers to specify a default field renaming strategy for enum values at a project level via build.yaml. This change provides a more streamlined and less verbose way to manage enum serialization, reducing boilerplate code and improving consistency across the codebase by centralizing renaming rules. It addresses a long-standing limitation where field_rename only applied to class fields, not enum values.

Highlights

  • New Configuration Option: Introduced enum_field_rename in build.yaml for json_serializable to define a package-wide default renaming strategy for enum values, eliminating the need for repetitive @JsonEnum annotations.
  • Enum Renaming Logic: Enum values will now use the fieldRename specified in @JsonEnum if present and not none; otherwise, they will fall back to the enum_field_rename setting from build.yaml.
  • Annotation Integration: The JsonSerializable annotation now includes an enumFieldRename property, primarily used for parsing build.yaml configurations.
  • Internal Refactoring: Core generator logic in json_serializable has been updated to propagate and apply the new enumFieldRename setting to enum processing functions, ensuring consistent behavior.
  • Documentation and Testing: Updated README.md files and added comprehensive tests for configuration parsing, invalid input handling, and the overall behavior of the new enum_field_rename option.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the enum_field_rename option, allowing a package-wide default for renaming enum values during serialization. The implementation is comprehensive, with updates to configuration handling, code generation, tests, and documentation. The changes are well-structured and align with the feature's goal. I've identified a couple of areas for improvement: one regarding a contradiction between documentation and implementation, and another suggesting a user-facing warning for a potentially confusing configuration scenario. Overall, this is a solid contribution that enhances the flexibility of json_serializable.

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 1, 2026

Gah! i like this idea, but I'm working on something else this should plug into. Please hold!

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 2, 2026

Actually, I take that back. This approach is fine. But I'd like to see NOW tests that cover this!

Copy link
Collaborator

@kevmoo kevmoo left a comment

Choose a reason for hiding this comment

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

You need some NEW tests to cover this new behavior, please!

@jlalvarez18
Copy link
Author

@kevmoo ok cool! Adding tests now

@jlalvarez18
Copy link
Author

jlalvarez18 commented Feb 2, 2026

@kevmoo what do you mean by NOW tests?

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 2, 2026

@jlalvarez18 – I meant new – sorry. 😆

- enum_field_rename_test: programmatic JsonEnumGenerator tests for config enum_field_rename pascal, default (none), and @JsonEnum(fieldRename) overriding config.
- enum_utils_test: unit tests for enumValueMapFromType with defaultEnumFieldRename (pascal, null, annotation override).
- _json_enum_default_rename_test_input: EnumForDefaultRename and EnumWithKebabOverride used by both test files.
Log a build warning when JsonEnum.valueField is set and JsonEnum.fieldRename is not none, since fieldRename is ignored in that case. This avoids silently ignoring fieldRename and makes the behavior clear to users.

- In enum_utils.dart: import build, and call log.warning() when valueField != null and fieldRename != FieldRename.none
- Add test input enum with both options and a unit test that asserts the warning is recorded via buildLogItems
@jlalvarez18 jlalvarez18 requested a review from kevmoo February 2, 2026 17:58
@kevmoo
Copy link
Collaborator

kevmoo commented Feb 3, 2026

@jlalvarez18 – FYI I pushed a couple of tweaks here. In case you wonder why your git push doesn't work 😁

kevmoo
kevmoo previously requested changes Feb 3, 2026
@kevmoo kevmoo dismissed their stale review February 4, 2026 21:02

I fixed things

no need to churn this line!
@kevmoo
Copy link
Collaborator

kevmoo commented Feb 4, 2026

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a valuable feature by adding the enum_field_rename option, allowing for a package-wide default for enum field renaming. The implementation is solid and includes good test coverage. I've identified one high-severity issue where the code's behavior for enumFieldRename contradicts the documentation, and a medium-severity issue regarding a potentially duplicated and unused test file. Addressing these points will make this a great addition.

@jlalvarez18
Copy link
Author

@kevmoo anything else needed on my end to get this moving?

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 16, 2026

Just ran the robot. Will let you know!

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 16, 2026

Let's get CI green!

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 18, 2026

I'm reviewing the code now. Note that I pushed to get things green!

@kevmoo
Copy link
Collaborator

kevmoo commented Feb 18, 2026

@jlalvarez18 – okay, I did a bit more cleanup, but I'm...concerned about this plan.

We're adding a field to JsonSerializable that is NOT meant to be used in the annotation.

Which I really don't like.

I'm wondering now if we need to update the logic here to create a subclass of JsonSerializable that is used only for build.yaml parsing to have fields like this.

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configure fieldRename for enums in build.yaml

2 participants