if the message has an optional field with a return value, the proto will attach a same name field with `_` prefix. why?
Problem description
if the message has an option field with a return value, the proto will attach a same name field with _ prefix. why?
Reproduction steps
- message like this
message Res {
uint32 code = 1;
optional string msg = 2;
string status = 3;
optional string error = 4;
optional uint32 count = 5;
}
-
server retun
-
real result client got
Environment
- OS name, version and architecture: windows11
- Node version : 16.15
- Node installation method. binary
- If applicable, compiler version [e.g. clang 3.8.0-2ubuntu4]
- Package name and version: 1.10.8
Additional context
This is controlled by the message decoding code on the client. What protobuf implementation are you using on the client?
proto3 with @grpc/proto-loader.
this is protoLoaderOptions,
const protoLoaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
We got bit by this in our application recently where we were passing the response from a gRPC response through camelcase-keys, where when we got something like { msg: 'foo', _msg: 'msg' }, the camelcase version was { msg: 'msg' }.
While we can modify our usage of camelcase-keys, it'd be nice if the loader could just not have these _ fields as we don't view them as useful at all.
For reference, we're also using @grpc/proto-loader with the same settings as above.
OK, I see what's happening here: Protobuf.js internally represents optional fields as a single-member oneof group named as the underscore-prefixed field name. The plain object message representation includes the oneof group as a separate key to indicate which member is set because you set the oneofs option to true.
You can disable this behavior by setting the oneofs option to false.
This behavior can only be changed in Protobuf.js, so I have filed an issue there: https://github.com/protobufjs/protobuf.js/issues/2037.