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

Allow stripping / adding back enum prefixes when encoding/decoding JSON #16121

Closed
dorner opened this issue Mar 11, 2024 · 2 comments
Closed

Allow stripping / adding back enum prefixes when encoding/decoding JSON #16121

dorner opened this issue Mar 11, 2024 · 2 comments
Labels
enhancement go Pull requests that update Go code golang json untriaged auto added to all issues by default when created.

Comments

@dorner
Copy link

dorner commented Mar 11, 2024

What language does this apply to?

Proto3 encoding and decoding to JSON. Looked at this with Go, but it applies across the board.

Describe the problem you are trying to solve.

This was originally posted in golang/protobuf#1598 .

The accepted approach to avoid namespace collisions with Protobuf enums is to prefix them, e.g.

enum PurchaseMethod {
  PURCHASE_METHOD_UNSPECIFIED = 0;
  PURCHASE_METHOD_ONLINE = 1;
  PURCHASE_METHOD_IN_STORE = 2;
}

Tools like buf will actually lint this and not allow you to check in a proto file where this doesn't happen.

When encoding to JSON, this results in a "stutter" like so:

{ purchase_method: "PURCHASE_METHOD_IN_STORE" }

There is an existing discussion here regarding fixing the Go code generation, which might ease the namespace issues. But that discussion has been ongoing since 2018 without a resolution.

Describe the solution you'd like

I was hoping to at least be able to make protojson and other JSON encoders "smarter" in this case to give it an option to remove the stuttering. This would involve an additional option which could remove the shared prefix on encoding, and add it back on decoding, to allow the generated JSON to be slimmer and easier to read.

Describe alternatives you've considered

Really the only way to "fix this" fix this would be to relax the namespacing requirement entirely and allow for generation of non-prefixed enums. I imagine this would be quite hairy to enable. Limiting this to the JSON generation would give us at least some relief.

Additional context

This is a sample PR for how this would work on the Go side (I tested it and it does work - obviously we wouldn't include the dependency I added there for the sake of getting it working faster).

First issue here, so please let me know if anything needs more info or a different approach to spark discussion.

@dorner dorner added the untriaged auto added to all issues by default when created. label Mar 11, 2024
@EraYaN
Copy link

EraYaN commented Jun 4, 2024

The C# generator already removes the type name from the Enum values too. It would be great if the behaviour was consistent. And shorter names are always good, especially in languages that require you to include the enum everytime anyway. SomeEnum.SOME_ENUM_VALUE1 just looks worse than SomeEnum.VALUE1.

@esorot esorot added enhancement golang go Pull requests that update Go code json labels Jul 9, 2024
@esrauchg
Copy link

esrauchg commented Oct 2, 2024

Thanks for opening this and sorry that this fell through the cracks to getting an official reply!

The bad news is that we can't really make the proposed change to the spec / official serializers; really we try to keep the ProtoJSON spec lean and try to keep all serializer options should only emit code that is still with in spec and keep all of the official parsers/serializers to be compatible in such a way that if you use any serializer with any option in any language it should emit ProtoJSON that should still be cleanly parsable by any other language's parser without options on the parser side.

Although it would be possible to expand the spec to allow both prefixed and unprefixed enums, have it be an option on the serializer, and update all parsers to accept either, the benefits of losing the prefix are unlikely to justify the costs to do that (and it would introduces a significant 'confusion' problem where a serializer will pick to strip prefixes or not, and when it talks to a client that doesn't speak protobuf and just does a vanilla JSON.parse(), the other side would need to know to look for the stripped or unstripped names).

The somewhat good news is that we know this is a painpoint, and we intend to fix it by adding a feature that makes enum values be semantically scoped to the enum that contains them and flip that over to a default in a future edition; with that change it would make it so there is no reason to continue to prefix the constants at all.

The somewhat bad news is that we only make these kind of significant impacting changes (which many impact different protoc plugins / code generators) at Edition release boundaries now, which we do every year. While we intend to make this change, its not going to happen for the 2024 Edition (which will publicly release Q1 2025), so it's more likely that we will add it in the 2025 Edition (which will publicly release Q1 2026). Obviously thats unfortunately ~1.5 years from this moment until you could take advantage of it.

@esrauchg esrauchg closed this as completed Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement go Pull requests that update Go code golang json untriaged auto added to all issues by default when created.
Projects
None yet
Development

No branches or pull requests

4 participants