bufbuild / protobuf-es

Protocol Buffers for ECMAScript. The only JavaScript Protobuf library that is fully-compliant with Protobuf conformance tests.
Apache License 2.0
1.16k stars 69 forks source link

Go - JSON - TS casing difference #302

Closed fabius closed 2 years ago

fabius commented 2 years ago

Assuming one adheres to buf lint's naming convention (snake_case for casing), using protoc-gen-go generates snake_cased json tags for each message's go-struct representation. The TS types are camelCased as per TS/ES standards. Thus, one cannot marshal go-structs to JSON and load it in your TS code.

Describe the solution you'd like I'd love to have an option to either have the go-struct json tags be camelCased or, even though it's weird in terms of TS style guides, have the TS types be snake_cased so that marshalling and unmarshalling / loading works as expected.

Describe alternatives you've considered Manually fixing the casing / using something like retag

timostamm commented 2 years ago

one cannot marshal go-structs to JSON and load it in your TS code

You can! protojson.Marshal serializes your message to JSON in Go, and the method fromJsonString() parses from JSON in TS. This interoperability is a crucial feature and it definitely works reliably.

What you can't do is json.Marshal a message in Go. See the explanation in this comment:

The generation of the json tag pre-dated the formalization of the JSON<->PB specification. In it's current state, using encoding/json does not produce JSON that conforms to any particular pre-defined schema.

For similar reasons, you cannot JSON.parse() a message in TS. Our fromJsonString() methods use JSON.parse() under the hood, but they also take care of field name variations and other details that protobuf and TypeScript can represent, but JSON cannot, for example NaN. It also gives you structural validation when parsing JSON and is interoperable with all other protobuf implementations.

Closing this, but let us know if you think there's a missing piece.