encoding/protojson: add MarshalOptions.UseEnumNumbers

UseEnumNumbers=true will emit enum values as JSON numbers.

Change-Id: I6f3c814e06dc1e3dd595ad35aa79871a49718cd5
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/194017
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Herbie Ong 2019-09-06 14:35:09 -07:00
parent 984e528fd1
commit 9111f3b439
2 changed files with 62 additions and 7 deletions

View File

@ -34,6 +34,9 @@ type MarshalOptions struct {
// Marshal will return error if there are any missing required fields.
AllowPartial 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:
@ -197,14 +200,16 @@ func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor)
case pref.EnumKind:
if fd.Enum().FullName() == "google.protobuf.NullValue" {
o.encoder.WriteNull()
} else if desc := fd.Enum().Values().ByNumber(val.Enum()); desc != nil {
err := o.encoder.WriteString(string(desc.Name()))
if err != nil {
return err
}
} else {
// Use numeric value if there is no enum value descriptor.
o.encoder.WriteInt(int64(val.Enum()))
desc := fd.Enum().Values().ByNumber(val.Enum())
if o.UseEnumNumbers || desc == nil {
o.encoder.WriteInt(int64(val.Enum()))
} else {
err := o.encoder.WriteString(string(desc.Name()))
if err != nil {
return err
}
}
}
case pref.MessageKind, pref.GroupKind:

View File

@ -2124,6 +2124,56 @@ func TestMarshal(t *testing.T) {
"optNested": null
}
]
}`,
}, {
desc: "UseEnumNumbers in singular field",
mo: protojson.MarshalOptions{UseEnumNumbers: true},
input: &pb2.Enums{
OptEnum: pb2.Enum_ONE.Enum(),
OptNestedEnum: pb2.Enums_UNO.Enum(),
},
want: `{
"optEnum": 1,
"optNestedEnum": 1
}`,
}, {
desc: "UseEnumNumbers in repeated field",
mo: protojson.MarshalOptions{UseEnumNumbers: true},
input: &pb2.Enums{
RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_UNO, pb2.Enums_DOS, 47},
},
want: `{
"rptEnum": [
1,
2,
10,
42
],
"rptNestedEnum": [
1,
2,
47
]
}`,
}, {
desc: "UseEnumNumbers in map field",
mo: protojson.MarshalOptions{UseEnumNumbers: true},
input: &pb3.Maps{
Uint64ToEnum: map[uint64]pb3.Enum{
1: pb3.Enum_ONE,
2: pb3.Enum_TWO,
10: pb3.Enum_TEN,
47: 47,
},
},
want: `{
"uint64ToEnum": {
"1": 1,
"2": 2,
"10": 10,
"47": 47
}
}`,
}}