Skip to content

Commit 212014e

Browse files
committed
jsonpb: don't depend on stable struct field indexes
Fix for WKT protos generated after https://go-review.googlesource.com/c/protobuf/+/188979 Change-Id: I679f4b83e32b22079115787cf921eb78618512a7 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/189637 Reviewed-by: Joe Tsai <[email protected]>
1 parent 7037721 commit 212014e

File tree

3 files changed

+34
-27
lines changed

3 files changed

+34
-27
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module github.com/golang/protobuf
22

33
go 1.9
44

5-
require google.golang.org/protobuf v0.0.0-20190717230113-f647c82cc3c7
5+
require google.golang.org/protobuf v0.0.0-20190808204900-1799d1111a45

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ github.com/golang/protobuf v1.2.1-0.20190523175523-a1331f0b4ab4/go.mod h1:G+fNMo
66
github.com/golang/protobuf v1.2.1-0.20190605195750-76c9e09470ba/go.mod h1:S1YIJXvYHGRCG2UmZsOcElkAYfvZLg2sDRr9+Xu8JXU=
77
github.com/golang/protobuf v1.2.1-0.20190617175902-f94016f5239f/go.mod h1:G+HpKX7pYZAVkElkAWZkr08MToW6pTp/vs+E9osFfbg=
88
github.com/golang/protobuf v1.2.1-0.20190620192300-1ee46dfd80dd/go.mod h1:+CMAsi9jpYf/wAltLUKlg++CWXqxCJyD8iLDbQONsJs=
9+
github.com/golang/protobuf v1.2.1-0.20190806214225-7037721e6de0/go.mod h1:tDQPRlaHYu9yt1wPgdx85inRiLvUCuJZXsYjC0mwc1c=
910
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
1011
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
1112
google.golang.org/protobuf v0.0.0-20190514172829-e89e6244e0e8/go.mod h1:791zQGC15vDqjpmPRn1uGPu5oHy/Jzw/Q1n5JsgIIcY=
@@ -18,3 +19,5 @@ google.golang.org/protobuf v0.0.0-20190617175724-bd7b7a9e0c26/go.mod h1:+FOB8T5/
1819
google.golang.org/protobuf v0.0.0-20190620020611-d888139e7b59/go.mod h1:of3pt14Y+dOxz2tBOHXEoapPpKFC15/0zWhPAddkfsU=
1920
google.golang.org/protobuf v0.0.0-20190717230113-f647c82cc3c7 h1:U6U+Hb+UKNGJB0eMAjUGk0wTmy73kduTIvdsEgA4Gf8=
2021
google.golang.org/protobuf v0.0.0-20190717230113-f647c82cc3c7/go.mod h1:yGm7aNHn9Bp1NIvj6+CVUkcJshu+Usshfd3A+YxEuI8=
22+
google.golang.org/protobuf v0.0.0-20190808204900-1799d1111a45 h1:SZXAIsI6RiG0T8bAF4dqHDHgdqJtOa6tkofjswKtU20=
23+
google.golang.org/protobuf v0.0.0-20190808204900-1799d1111a45/go.mod h1:tRqhEyKwbKqwt5CQZAuOtj09RfhLNklDOhndhYA9blU=

jsonpb/jsonpb.go

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,14 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
196196
// "Wrappers use the same representation in JSON
197197
// as the wrapped primitive type, ..."
198198
sprop := proto.GetProperties(s.Type())
199-
return m.marshalValue(out, sprop.Prop[1], s.Field(1), indent)
199+
return m.marshalValue(out, sprop.Prop[1], s.FieldByName("Value"), indent)
200200
case "Any":
201201
// Any is a bit more involved.
202202
return m.marshalAny(out, v, indent)
203203
case "Duration":
204204
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
205205
// depending on required precision."
206-
s, ns := s.Field(1).Int(), s.Field(2).Int()
206+
s, ns := s.FieldByName("Seconds").Int(), s.FieldByName("Nanos").Int()
207207
if ns <= -secondInNanos || ns >= secondInNanos {
208208
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
209209
}
@@ -221,14 +221,18 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
221221
out.write(x)
222222
out.write(`s"`)
223223
return out.err
224-
case "Struct", "ListValue":
225-
// Let marshalValue handle the `Struct.fields` map or the `ListValue.values` slice.
224+
case "Struct":
225+
// Let marshalValue handle the `Struct.fields` map.
226+
// TODO: pass the correct Properties if needed.
227+
return m.marshalValue(out, &proto.Properties{}, s.FieldByName("Fields"), indent)
228+
case "ListValue":
229+
// Let marshalValue handle the `ListValue.values` slice.
226230
// TODO: pass the correct Properties if needed.
227-
return m.marshalValue(out, &proto.Properties{}, s.Field(1), indent)
231+
return m.marshalValue(out, &proto.Properties{}, s.FieldByName("Values"), indent)
228232
case "Timestamp":
229233
// "RFC 3339, where generated output will always be Z-normalized
230234
// and uses 0, 3, 6 or 9 fractional digits."
231-
s, ns := s.Field(1).Int(), s.Field(2).Int()
235+
s, ns := s.FieldByName("Seconds").Int(), s.FieldByName("Nanos").Int()
232236
if ns < 0 || ns >= secondInNanos {
233237
return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
234238
}
@@ -244,7 +248,7 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
244248
return out.err
245249
case "Value":
246250
// Value has a single oneof.
247-
kind := s.Field(1)
251+
kind := s.FieldByName("Kind")
248252
if kind.IsNil() {
249253
// "absence of any variant indicates an error"
250254
return errors.New("nil Value")
@@ -393,8 +397,8 @@ func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string)
393397
// Otherwise, the value will be converted into a JSON object,
394398
// and the "@type" field will be inserted to indicate the actual data type."
395399
v := reflect.ValueOf(any).Elem()
396-
turl := v.Field(1).String()
397-
val := v.Field(2).Bytes()
400+
turl := v.FieldByName("TypeUrl").String()
401+
val := v.FieldByName("Value").Bytes()
398402

399403
var msg proto.Message
400404
var err error
@@ -723,7 +727,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
723727
switch wellKnownType(target.Addr().Interface()) {
724728
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
725729
"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
726-
return u.unmarshalValue(target.Field(1), inputValue, prop)
730+
return u.unmarshalValue(target.FieldByName("Value"), inputValue, prop)
727731
case "Any":
728732
// Use json.RawMessage pointer type instead of value to support pre-1.8 version.
729733
// 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see
@@ -742,7 +746,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
742746
if err := json.Unmarshal([]byte(*val), &turl); err != nil {
743747
return fmt.Errorf("can't unmarshal Any's '@type': %q", *val)
744748
}
745-
target.Field(1).SetString(turl)
749+
target.FieldByName("TypeUrl").SetString(turl)
746750

747751
var m proto.Message
748752
var err error
@@ -780,7 +784,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
780784
if err != nil {
781785
return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err)
782786
}
783-
target.Field(2).SetBytes(b)
787+
target.FieldByName("Value").SetBytes(b)
784788

785789
return nil
786790
case "Duration":
@@ -797,8 +801,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
797801
ns := d.Nanoseconds()
798802
s := ns / 1e9
799803
ns %= 1e9
800-
target.Field(1).SetInt(s)
801-
target.Field(2).SetInt(ns)
804+
target.FieldByName("Seconds").SetInt(s)
805+
target.FieldByName("Nanos").SetInt(ns)
802806
return nil
803807
case "Timestamp":
804808
unq, err := unquote(string(inputValue))
@@ -811,22 +815,22 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
811815
return fmt.Errorf("bad Timestamp: %v", err)
812816
}
813817

814-
target.Field(1).SetInt(t.Unix())
815-
target.Field(2).SetInt(int64(t.Nanosecond()))
818+
target.FieldByName("Seconds").SetInt(t.Unix())
819+
target.FieldByName("Nanos").SetInt(int64(t.Nanosecond()))
816820
return nil
817821
case "Struct":
818822
var m map[string]json.RawMessage
819823
if err := json.Unmarshal(inputValue, &m); err != nil {
820824
return fmt.Errorf("bad StructValue: %v", err)
821825
}
822826

823-
target.Field(1).Set(reflect.ValueOf(map[string]*stpb.Value{}))
827+
target.FieldByName("Fields").Set(reflect.ValueOf(map[string]*stpb.Value{}))
824828
for k, jv := range m {
825829
pv := &stpb.Value{}
826830
if err := u.unmarshalValue(reflect.ValueOf(pv).Elem(), jv, prop); err != nil {
827831
return fmt.Errorf("bad value in StructValue for key %q: %v", k, err)
828832
}
829-
target.Field(1).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv))
833+
target.FieldByName("Fields").SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv))
830834
}
831835
return nil
832836
case "ListValue":
@@ -835,30 +839,30 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
835839
return fmt.Errorf("bad ListValue: %v", err)
836840
}
837841

838-
target.Field(1).Set(reflect.ValueOf(make([]*stpb.Value, len(s))))
842+
target.FieldByName("Values").Set(reflect.ValueOf(make([]*stpb.Value, len(s))))
839843
for i, sv := range s {
840-
if err := u.unmarshalValue(target.Field(1).Index(i), sv, prop); err != nil {
844+
if err := u.unmarshalValue(target.FieldByName("Values").Index(i), sv, prop); err != nil {
841845
return err
842846
}
843847
}
844848
return nil
845849
case "Value":
846850
ivStr := string(inputValue)
847851
if ivStr == "null" {
848-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_NullValue{}))
852+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_NullValue{}))
849853
} else if v, err := strconv.ParseFloat(ivStr, 0); err == nil {
850-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_NumberValue{v}))
854+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_NumberValue{v}))
851855
} else if v, err := unquote(ivStr); err == nil {
852-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_StringValue{v}))
856+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_StringValue{v}))
853857
} else if v, err := strconv.ParseBool(ivStr); err == nil {
854-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_BoolValue{v}))
858+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_BoolValue{v}))
855859
} else if err := json.Unmarshal(inputValue, &[]json.RawMessage{}); err == nil {
856860
lv := &stpb.ListValue{}
857-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_ListValue{lv}))
861+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_ListValue{lv}))
858862
return u.unmarshalValue(reflect.ValueOf(lv).Elem(), inputValue, prop)
859863
} else if err := json.Unmarshal(inputValue, &map[string]json.RawMessage{}); err == nil {
860864
sv := &stpb.Struct{}
861-
target.Field(1).Set(reflect.ValueOf(&stpb.Value_StructValue{sv}))
865+
target.FieldByName("Kind").Set(reflect.ValueOf(&stpb.Value_StructValue{sv}))
862866
return u.unmarshalValue(reflect.ValueOf(sv).Elem(), inputValue, prop)
863867
} else {
864868
return fmt.Errorf("unrecognized type for Value %q", ivStr)

0 commit comments

Comments
 (0)