Skip to content

Commit 2ab1774

Browse files
committed
jsonpb: bring back old behaviour of handling nulls and JSONPBUnmarshaler
Change how jsonpb.Unmarshal handles nested JSONPBMarshaler fields a null json values. When json null is encountered for a field which implements JSONPBUnmarshaler, jsonpb will now calli unmarshal method from the field, instead of just assigning nil to this field.
1 parent a36a1a1 commit 2ab1774

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

Diff for: jsonpb/decode.go

+21-6
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,14 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
135135
md := m.Descriptor()
136136
fds := md.Fields()
137137

138-
if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
139-
return nil
140-
}
141-
142138
if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok {
143139
return jsu.UnmarshalJSONPB(u, in)
144140
}
145141

142+
if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
143+
return nil
144+
}
145+
146146
switch wellKnownType(md.FullName()) {
147147
case "Any":
148148
var jsonObject map[string]json.RawMessage
@@ -332,11 +332,12 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
332332
raw = v
333333
}
334334

335+
field := m.NewField(fd)
335336
// Unmarshal the field value.
336-
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) {
337+
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isUnmarshalJSONPB(field, fd)) {
337338
continue
338339
}
339-
v, err := u.unmarshalValue(m.NewField(fd), raw, fd)
340+
v, err := u.unmarshalValue(field, raw, fd)
340341
if err != nil {
341342
return err
342343
}
@@ -390,6 +391,20 @@ func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
390391
return false
391392
}
392393

394+
func isUnmarshalJSONPB(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool {
395+
if fd.Kind() != protoreflect.MessageKind {
396+
return false
397+
}
398+
if fd.Cardinality() == protoreflect.Repeated {
399+
return false
400+
}
401+
402+
i := v.Interface()
403+
m := proto.MessageV1(i)
404+
_, ok := m.(JSONPBUnmarshaler)
405+
return ok
406+
}
407+
393408
func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
394409
switch {
395410
case fd.IsList():

Diff for: jsonpb/json_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
10091009
t.Errorf("unmarshal error: %v", err)
10101010
}
10111011

1012-
want := ptrFieldMessage{}
1012+
want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
10131013
if !proto.Equal(&ptrFieldMsg, &want) {
10141014
t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
10151015
}

0 commit comments

Comments
 (0)