mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-02-06 09:40:07 +00:00
encoding/jsonpb: fix encoding of empty google.protobuf.Value
Description of message Value states: `Value` represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values. A producer of value is expected to set one of that variants, absence of any variant indicates an error. https://github.com/protocolbuffers/protobuf/blob/3.7.x/src/google/protobuf/struct.proto#L57-L60 Previous implementation was following C++ lib behavior. Change-Id: Id51792e2fc8cc465a05a978e63410d3b6802b522 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/168901 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
a3421952ac
commit
1c7462c1ba
@ -111,14 +111,8 @@ func (e encoder) marshalFields(m pref.Message) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// An empty google.protobuf.Value should NOT be marshaled out.
|
|
||||||
// Hence need to check ahead for this.
|
|
||||||
val := knownFields.Get(num)
|
|
||||||
if isEmptyKnownValue(val, fd.MessageType()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name := fd.JSONName()
|
name := fd.JSONName()
|
||||||
|
val := knownFields.Get(num)
|
||||||
if err := e.WriteName(name); !nerr.Merge(err) {
|
if err := e.WriteName(name); !nerr.Merge(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1008,15 +1008,15 @@ func TestMarshal(t *testing.T) {
|
|||||||
input: &knownpb.Empty{},
|
input: &knownpb.Empty{},
|
||||||
want: `{}`,
|
want: `{}`,
|
||||||
}, {
|
}, {
|
||||||
desc: "Value empty",
|
desc: "Value empty",
|
||||||
input: &knownpb.Value{},
|
input: &knownpb.Value{},
|
||||||
want: ``,
|
wantErr: true,
|
||||||
}, {
|
}, {
|
||||||
desc: "Value empty field",
|
desc: "Value empty field",
|
||||||
input: &pb2.KnownTypes{
|
input: &pb2.KnownTypes{
|
||||||
OptValue: &knownpb.Value{},
|
OptValue: &knownpb.Value{},
|
||||||
},
|
},
|
||||||
want: `{}`,
|
wantErr: true,
|
||||||
}, {
|
}, {
|
||||||
desc: "Value contains NullValue",
|
desc: "Value contains NullValue",
|
||||||
input: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
|
input: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
|
||||||
@ -1531,7 +1531,7 @@ func TestMarshal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
input: func() proto.Message {
|
input: func() proto.Message {
|
||||||
m := &knownpb.Value{}
|
m := &knownpb.Value{}
|
||||||
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
b, err := proto.Marshal(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
||||||
}
|
}
|
||||||
@ -1540,9 +1540,7 @@ func TestMarshal(t *testing.T) {
|
|||||||
Value: b,
|
Value: b,
|
||||||
}
|
}
|
||||||
}(),
|
}(),
|
||||||
want: `{
|
wantErr: true,
|
||||||
"@type": "type.googleapis.com/google.protobuf.Value"
|
|
||||||
}`,
|
|
||||||
}, {
|
}, {
|
||||||
desc: "Any with Duration",
|
desc: "Any with Duration",
|
||||||
mo: jsonpb.MarshalOptions{
|
mo: jsonpb.MarshalOptions{
|
||||||
@ -1641,7 +1639,9 @@ func TestMarshal(t *testing.T) {
|
|||||||
{Kind: &knownpb.Value_ListValue{}},
|
{Kind: &knownpb.Value_ListValue{}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OptValue: &knownpb.Value{},
|
OptValue: &knownpb.Value{
|
||||||
|
Kind: &knownpb.Value_StringValue{"world"},
|
||||||
|
},
|
||||||
OptEmpty: &knownpb.Empty{},
|
OptEmpty: &knownpb.Empty{},
|
||||||
OptAny: &knownpb.Any{
|
OptAny: &knownpb.Any{
|
||||||
TypeUrl: "google.protobuf.Empty",
|
TypeUrl: "google.protobuf.Empty",
|
||||||
@ -1671,6 +1671,7 @@ func TestMarshal(t *testing.T) {
|
|||||||
{},
|
{},
|
||||||
[]
|
[]
|
||||||
],
|
],
|
||||||
|
"optValue": "world",
|
||||||
"optEmpty": {},
|
"optEmpty": {},
|
||||||
"optAny": {
|
"optAny": {
|
||||||
"@type": "google.protobuf.Empty"
|
"@type": "google.protobuf.Empty"
|
||||||
|
@ -128,10 +128,6 @@ func (e encoder) marshalAny(m pref.Message) error {
|
|||||||
// with corresponding custom JSON encoding of the embedded message as a
|
// with corresponding custom JSON encoding of the embedded message as a
|
||||||
// field.
|
// field.
|
||||||
if isCustomType(emt.FullName()) {
|
if isCustomType(emt.FullName()) {
|
||||||
// An empty google.protobuf.Value should NOT be marshaled out.
|
|
||||||
if isEmptyKnownValue(pref.ValueOf(em), emt) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
e.WriteName("value")
|
e.WriteName("value")
|
||||||
return e.marshalCustomType(em)
|
return e.marshalCustomType(em)
|
||||||
}
|
}
|
||||||
@ -176,14 +172,6 @@ func (e encoder) marshalListValue(m pref.Message) error {
|
|||||||
return e.marshalList(val.List(), fd)
|
return e.marshalList(val.List(), fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isEmptyKnownValue returns true if given val is of type google.protobuf.Value
|
|
||||||
// and does not have any of its oneof fields set.
|
|
||||||
func isEmptyKnownValue(val pref.Value, md pref.MessageDescriptor) bool {
|
|
||||||
return md != nil &&
|
|
||||||
md.FullName() == "google.protobuf.Value" &&
|
|
||||||
val.Message().KnownFields().Len() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e encoder) marshalKnownValue(m pref.Message) error {
|
func (e encoder) marshalKnownValue(m pref.Message) error {
|
||||||
msgType := m.Type()
|
msgType := m.Type()
|
||||||
fieldDescs := msgType.Oneofs().Get(0).Fields()
|
fieldDescs := msgType.Oneofs().Get(0).Fields()
|
||||||
@ -200,8 +188,8 @@ func (e encoder) marshalKnownValue(m pref.Message) error {
|
|||||||
return e.marshalSingular(val, fd)
|
return e.marshalSingular(val, fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// None of the fields are set.
|
// Return error if none of the fields are set.
|
||||||
return nil
|
return errors.New("%s: none of the variants is set", msgType.FullName())
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user