Skip to content

Commit 62e4364

Browse files
committed
jsonpb: Accept both camelCase and orig_name as field names for oneof fields.
Fixes #148.
1 parent 9951127 commit 62e4364

File tree

4 files changed

+121
-80
lines changed

4 files changed

+121
-80
lines changed

jsonpb/jsonpb.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -517,30 +517,39 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
517517
return err
518518
}
519519

520-
sprops := proto.GetProperties(targetType)
521-
for i := 0; i < target.NumField(); i++ {
522-
ft := target.Type().Field(i)
523-
if strings.HasPrefix(ft.Name, "XXX_") {
524-
continue
525-
}
520+
consumeField := func(prop *proto.Properties) (json.RawMessage, bool) {
526521
// Be liberal in what names we accept; both orig_name and camelName are okay.
527-
fieldNames := acceptedJSONFieldNames(ft)
522+
fieldNames := acceptedJSONFieldNames(prop)
528523

529524
vOrig, okOrig := jsonFields[fieldNames.orig]
530525
vCamel, okCamel := jsonFields[fieldNames.camel]
531526
if !okOrig && !okCamel {
532-
continue
527+
return nil, false
533528
}
534529
// If, for some reason, both are present in the data, favour the camelName.
535-
var valueForField json.RawMessage
530+
var raw json.RawMessage
536531
if okOrig {
537-
valueForField = vOrig
532+
raw = vOrig
538533
delete(jsonFields, fieldNames.orig)
539534
}
540535
if okCamel {
541-
valueForField = vCamel
536+
raw = vCamel
542537
delete(jsonFields, fieldNames.camel)
543538
}
539+
return raw, true
540+
}
541+
542+
sprops := proto.GetProperties(targetType)
543+
for i := 0; i < target.NumField(); i++ {
544+
ft := target.Type().Field(i)
545+
if strings.HasPrefix(ft.Name, "XXX_") {
546+
continue
547+
}
548+
549+
valueForField, ok := consumeField(sprops.Prop[i])
550+
if !ok {
551+
continue
552+
}
544553

545554
// Handle enums, which have an underlying type of int32,
546555
// and may appear as strings. We do this while handling
@@ -570,14 +579,17 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
570579
}
571580
}
572581
// Check for any oneof fields.
573-
for fname, raw := range jsonFields {
574-
if oop, ok := sprops.OneofTypes[fname]; ok {
582+
if len(jsonFields) > 0 {
583+
for _, oop := range sprops.OneofTypes {
584+
raw, ok := consumeField(oop.Prop)
585+
if !ok {
586+
continue
587+
}
575588
nv := reflect.New(oop.Type.Elem())
576589
target.Field(oop.Field).Set(nv)
577590
if err := unmarshalValue(nv.Elem().Field(0), raw); err != nil {
578591
return err
579592
}
580-
delete(jsonFields, fname)
581593
}
582594
}
583595
if len(jsonFields) > 0 {
@@ -663,9 +675,7 @@ type fieldNames struct {
663675
orig, camel string
664676
}
665677

666-
func acceptedJSONFieldNames(f reflect.StructField) fieldNames {
667-
var prop proto.Properties
668-
prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
678+
func acceptedJSONFieldNames(prop *proto.Properties) fieldNames {
669679
opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName}
670680
if prop.JSONName != "" {
671681
opts.camel = prop.JSONName

jsonpb/jsonpb_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ var unmarshalingTests = []struct {
379379
{"map<string, string>", `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
380380
{"map<int32, Object>", `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
381381
{"oneof", `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
382+
{"oneof spec name", `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
383+
{"oneof orig_name", `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
382384
{"orig_name input", `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
383385
{"camelName input", `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
384386

jsonpb/jsonpb_test_proto/test_objects.pb.go

Lines changed: 91 additions & 63 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsonpb/jsonpb_test_proto/test_objects.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ message MsgWithOneof {
9494
oneof union {
9595
string title = 1;
9696
int64 salary = 2;
97+
string Country = 3;
9798
}
9899
}
99100

0 commit comments

Comments
 (0)