danielgtaylor / python-betterproto

Clean, modern, Python 3.6+ code generator & library for Protobuf 3 and async gRPC
MIT License
1.51k stars 214 forks source link

PascalCase support #89

Open jameslan opened 4 years ago

jameslan commented 4 years ago

For a PascalCase field, betterproto uses the snake case in the class field, and can handle multiple cases in input json. However, it converts it to the camel case in output json, while protobuf requires a pascal case in the input. This makes the json incompatible.

For example,

message Test {
  int32 camelCase = 1;
  my_enum snake_case = 2;
  snake_case_message snake_case_message = 3;
  int32 PascalCase =4;
}

betterproto will output

{"camelCase": 1, "pascalCase": 3, "snakeCase": "ONE"}

but protobuf is expecting

{"PascalCase": 3, "camelCase": 1, "snakeCase": "ONE"}
boukeversteegh commented 4 years ago

I think what would be needed to solve this is actually storing the original field name inside the generated field definition.

We currently do some case conversion to make the python fields, and use that to generate back the json, with one of two casing settings (CAMEL or SNAKE). This causes the original casing to be lost.

@jameslan Do you know what the rules are for generating json fields? Is it the original fieldname in camelcase, preserving first capital?

Or are the rules more flexible?

jameslan commented 4 years ago

Just did some research.

Weirdly, the spec states that

  • Use proto field name instead of lowerCamelCase name: By default proto3 JSON printer should convert the field name to lowerCamelCase and use that as the JSON name. An implementation may provide an option to use proto field name as the JSON name instead. Proto3 JSON parsers are required to accept both the converted lowerCamelCase name and the proto field name.

But when I used pascalCase in the JSON file, I got the error from google.protobuf.json_format:

E           google.protobuf.json_format.ParseError: Message type "Test" has no field named "pascalCase".
E            Available Fields(except extensions): ['camelCase', 'snakeCase', 'snakeCaseMessage', 'PascalCase']

betterproto's current behavior is compliant with the doc, but incompatible with google.protobuf