encoding/protojson: add MarshalOptions.UseProtoNames

UseProtoNames=true uses proto field name in JSON field names.

Change-Id: I23249dc1787d9735bef780b1ef8d294a9c55c043
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/193998
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Herbie Ong 2019-09-06 15:17:22 -07:00
parent 9111f3b439
commit 956cd6ddcd
2 changed files with 62 additions and 11 deletions

View File

@ -34,23 +34,27 @@ type MarshalOptions struct {
// Marshal will return error if there are any missing required fields.
AllowPartial bool
// UseProtoNames uses proto field name instead of lowerCamelCase name in JSON
// field names.
UseProtoNames bool
// UseEnumNumbers emits enum values as numbers.
UseEnumNumbers bool
// EmitUnpopulated specifies whether to emit unpopulated fields. It does not
// emit unpopulated oneof fields or unpopulated extension fields.
// The JSON value emitted for unpopulated fields are as follows:
// ╔═══════╤════════════════════════════╗
// ║ JSON │ Protobuf field ║
// ╠═══════╪════════════════════════════╣
// ║ false │ proto3 boolean fields ║
// ║ 0 │ proto3 numeric fields ║
// ║ "" │ proto3 string/bytes fields ║
// ║ null │ proto2 scalar fields ║
// ║ null │ message fields ║
// ║ [] │ list fields ║
// ║ {} │ map fields ║
// ╚═══════╧════════════════════════════╝
// ╔═══════╤════════════════════════════╗
// ║ JSON │ Protobuf field ║
// ╠═══════╪════════════════════════════╣
// ║ false │ proto3 boolean fields ║
// ║ 0 │ proto3 numeric fields ║
// ║ "" │ proto3 string/bytes fields ║
// ║ null │ proto2 scalar fields ║
// ║ null │ message fields ║
// ║ [] │ list fields ║
// ║ {} │ map fields ║
// ╚═══════╧════════════════════════════╝
EmitUnpopulated bool
// If Indent is a non-empty string, it causes entries for an Array or Object
@ -128,6 +132,13 @@ func (o MarshalOptions) marshalFields(m pref.Message) error {
}
name := fd.JSONName()
if o.UseProtoNames {
name = string(fd.Name())
// Use type name for group field name.
if fd.Kind() == pref.GroupKind {
name = string(fd.Message().Name())
}
}
if err := o.encoder.WriteName(name); err != nil {
return err
}

View File

@ -2174,6 +2174,46 @@ func TestMarshal(t *testing.T) {
"10": 10,
"47": 47
}
}`,
}, {
desc: "UseProtoNames",
mo: protojson.MarshalOptions{UseProtoNames: true},
input: &pb2.Nests{
OptNested: &pb2.Nested{},
Optgroup: &pb2.Nests_OptGroup{
OptString: proto.String("inside a group"),
OptNested: &pb2.Nested{
OptString: proto.String("nested message inside a group"),
},
Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
OptFixed32: proto.Uint32(47),
},
},
Rptgroup: []*pb2.Nests_RptGroup{
{
RptString: []string{"hello", "world"},
},
},
},
want: `{
"opt_nested": {},
"OptGroup": {
"opt_string": "inside a group",
"opt_nested": {
"opt_string": "nested message inside a group"
},
"OptNestedGroup": {
"opt_fixed32": 47
}
},
"RptGroup": [
{
"rpt_string": [
"hello",
"world"
]
}
]
}`,
}}