Skip to content

Commit

Permalink
jsonpb: fix unmarshal null to value that implements JSONPBUnmarshaler (
Browse files Browse the repository at this point in the history
…golang#429)

Unmarshal should use JSONPBUnmarshaler even for JSON null value.
  • Loading branch information
vaporz authored and cybrcodr committed Sep 20, 2017
1 parent ae59567 commit 130e6b0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
3 changes: 2 additions & 1 deletion jsonpb/jsonpb.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
if targetType.Kind() == reflect.Ptr {
// If input value is "null" and target is a pointer type, then the field should be treated as not set
// UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue.
if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) {
_, isJSONPBUnmarshaler := target.Interface().(JSONPBUnmarshaler)
if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) && !isJSONPBUnmarshaler {
return nil
}
target.Set(reflect.New(targetType.Elem()))
Expand Down
48 changes: 48 additions & 0 deletions jsonpb/jsonpb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,19 @@ func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
}
}

func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
rawJson := `{"stringField":null}`
var ptrFieldMsg ptrFieldMessage
if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil {
t.Errorf("unmarshal error: %v", err)
}

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

func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
var got anypb.Any
Expand Down Expand Up @@ -821,6 +834,41 @@ func init() {
proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
}

type ptrFieldMessage struct {
StringField *stringField `protobuf:"bytes,1,opt,name=stringField"`
}

func (m *ptrFieldMessage) Reset() {
}

func (m *ptrFieldMessage) String() string {
return m.StringField.StringValue
}

func (m *ptrFieldMessage) ProtoMessage() {
}

type stringField struct {
IsSet bool `protobuf:"varint,1,opt,name=isSet"`
StringValue string `protobuf:"bytes,2,opt,name=stringValue"`
}

func (s *stringField) Reset() {
}

func (s *stringField) String() string {
return s.StringValue
}

func (s *stringField) ProtoMessage() {
}

func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
s.IsSet = true
s.StringValue = string(js)
return nil
}

// dynamicMessage implements protobuf.Message but is not a normal generated message type.
// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
type dynamicMessage struct {
Expand Down

0 comments on commit 130e6b0

Please sign in to comment.