From 012e80c42199d642c492a271b6bc75f581df8661 Mon Sep 17 00:00:00 2001 From: marusama Date: Wed, 4 Apr 2018 17:57:46 +0300 Subject: [PATCH 1/2] emit null value for oneof field with 'nil-interface' value. example proto: message test { oneof roadIdNil { int32 roadId = 12; } } go code: ``` var roadId *proto.Test_RoadIdNil test.RoadIdNil = roadId ``` will produce json: { "roadId": null } instead of panic --- jsonpb/jsonpb.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jsonpb/jsonpb.go b/jsonpb/jsonpb.go index ff368f33c5..32d363aa31 100644 --- a/jsonpb/jsonpb.go +++ b/jsonpb/jsonpb.go @@ -316,9 +316,15 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. - sv := value.Elem().Elem() // interface -> *T -> T - value = sv.Field(0) - valueField = sv.Type().Field(0) + svPtr := value.Elem() // interface -> *T + if !svPtr.IsNil() { + sv := svPtr.Elem() // *T -> T + value = sv.Field(0) + valueField = sv.Type().Field(0) + } else { + value = reflect.ValueOf(nil) + valueField = svPtr.Type().Elem().Field(0) + } } prop := jsonProperties(valueField, m.OrigName) if !firstField { From 04e8c554184b10aa819c107eeb26b48cd76f5ad2 Mon Sep 17 00:00:00 2001 From: marusama Date: Thu, 5 Apr 2018 19:30:21 +0300 Subject: [PATCH 2/2] make nil-interface value for field: null --- jsonpb/jsonpb.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jsonpb/jsonpb.go b/jsonpb/jsonpb.go index 32d363aa31..5df6db1fc8 100644 --- a/jsonpb/jsonpb.go +++ b/jsonpb/jsonpb.go @@ -940,6 +940,13 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe if !ok { continue } + + if string(raw) == "null" { + nv := reflect.New(reflect.PtrTo(oop.Type.Elem())) + target.Field(oop.Field).Set(nv.Elem()) + continue + } + nv := reflect.New(oop.Type.Elem()) target.Field(oop.Field).Set(nv) if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {