Skip to content

Commit

Permalink
jsonpb: restore previous behavior for handling nulls and JSONPBUnmars…
Browse files Browse the repository at this point in the history
…haler (#1300)

When a JSON null is encountered for a field which implements JSONPBUnmarshaler,
jsonpb will now call the unmarshal method, instead of just skipping the field.
  • Loading branch information
krzysztofdrys authored Mar 24, 2021
1 parent a36a1a1 commit af94003
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
26 changes: 18 additions & 8 deletions jsonpb/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
md := m.Descriptor()
fds := md.Fields()

if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
return nil
}

if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok {
return jsu.UnmarshalJSONPB(u, in)
}

if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
return nil
}

switch wellKnownType(md.FullName()) {
case "Any":
var jsonObject map[string]json.RawMessage
Expand Down Expand Up @@ -332,11 +332,12 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
raw = v
}

field := m.NewField(fd)
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) {
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
continue
}
v, err := u.unmarshalValue(m.NewField(fd), raw, fd)
v, err := u.unmarshalValue(field, raw, fd)
if err != nil {
return err
}
Expand Down Expand Up @@ -364,11 +365,12 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName())
}

field := m.NewField(fd)
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) {
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) {
continue
}
v, err := u.unmarshalValue(m.NewField(fd), raw, fd)
v, err := u.unmarshalValue(field, raw, fd)
if err != nil {
return err
}
Expand All @@ -390,6 +392,14 @@ func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
return false
}

func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool {
if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated {
_, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler)
return ok
}
return false
}

func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch {
case fd.IsList():
Expand Down
2 changes: 1 addition & 1 deletion jsonpb/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
t.Errorf("unmarshal error: %v", err)
}

want := ptrFieldMessage{}
want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
if !proto.Equal(&ptrFieldMsg, &want) {
t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
}
Expand Down

0 comments on commit af94003

Please sign in to comment.