diff --git a/runtime/fieldmask.go b/runtime/fieldmask.go index 341aad5a3ea..aef645e40b9 100644 --- a/runtime/fieldmask.go +++ b/runtime/fieldmask.go @@ -58,11 +58,18 @@ func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*fie if subMsg, ok := v.(descriptor2.Message); ok { _, subMd = descriptor2.ForMessage(subMsg) } - queue = append(queue, fieldMaskPathItem{path: append(item.path, protoName), node: v, md: subMd}) + + var path string + if item.path == "" { + path = protoName + } else { + path = item.path + "." + protoName + } + queue = append(queue, fieldMaskPathItem{path: path, node: v, md: subMd}) } } else if len(item.path) > 0 { // otherwise, it's a leaf node so print its path - fm.Paths = append(fm.Paths, strings.Join(item.path, ".")) + fm.Paths = append(fm.Paths, item.path) } } @@ -71,8 +78,8 @@ func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*fie // fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask type fieldMaskPathItem struct { - // the list of prior fields leading up to node - path []string + // the list of prior fields leading up to node connected by dots + path string // a generic decoded json object the current item to inspect for further path extraction node interface{} diff --git a/runtime/fieldmask_test.go b/runtime/fieldmask_test.go index 7a5ddaae957..8789725d8d9 100644 --- a/runtime/fieldmask_test.go +++ b/runtime/fieldmask_test.go @@ -54,6 +54,7 @@ func TestFieldMaskFromRequestBody(t *testing.T) { {name: "simple", input: `{"foo":1, "bar":"baz"}`, expected: newFieldMask("foo", "bar")}, {name: "nested", input: `{"foo": {"bar":1, "baz": 2}, "qux": 3}`, expected: newFieldMask("foo.bar", "foo.baz", "qux")}, {name: "canonical", input: `{"f": {"b": {"d": 1, "x": 2}, "c": 1}}`, expected: newFieldMask("f.b.d", "f.b.x", "f.c")}, + {name: "deeply-nested", input: `{"foo": {"bar": {"baz": {"a": 1, "b": 2}}}}`, expected: newFieldMask("foo.bar.baz.a", "foo.bar.baz.b")}, } { t.Run(tc.name, func(t *testing.T) { actual, err := FieldMaskFromRequestBody(bytes.NewReader([]byte(tc.input)), nil)