...
1 package runtime
2
3 import (
4 "encoding/json"
5 "io"
6 "strings"
7
8 descriptor2 "github.com/golang/protobuf/descriptor"
9 "github.com/golang/protobuf/protoc-gen-go/descriptor"
10 "google.golang.org/genproto/protobuf/field_mask"
11 )
12
13 func translateName(name string, md *descriptor.DescriptorProto) (string, *descriptor.DescriptorProto) {
14
15 if md != nil {
16 for _, f := range md.Field {
17 if f.JsonName != nil && f.Name != nil && *f.JsonName == name {
18 var subType *descriptor.DescriptorProto
19
20
21 if f.TypeName != nil {
22 typeSplit := strings.Split(*f.TypeName, ".")
23 typeName := typeSplit[len(typeSplit)-1]
24 for _, t := range md.NestedType {
25 if typeName == *t.Name {
26 subType = t
27 }
28 }
29 }
30 return *f.Name, subType
31 }
32 }
33 }
34 return name, nil
35 }
36
37
38 func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*field_mask.FieldMask, error) {
39 fm := &field_mask.FieldMask{}
40 var root interface{}
41 if err := json.NewDecoder(r).Decode(&root); err != nil {
42 if err == io.EOF {
43 return fm, nil
44 }
45 return nil, err
46 }
47
48 queue := []fieldMaskPathItem{{node: root, md: md}}
49 for len(queue) > 0 {
50
51 item := queue[0]
52 queue = queue[1:]
53
54 if m, ok := item.node.(map[string]interface{}); ok {
55
56 for k, v := range m {
57 protoName, subMd := translateName(k, item.md)
58 if subMsg, ok := v.(descriptor2.Message); ok {
59 _, subMd = descriptor2.ForMessage(subMsg)
60 }
61
62 var path string
63 if item.path == "" {
64 path = protoName
65 } else {
66 path = item.path + "." + protoName
67 }
68 queue = append(queue, fieldMaskPathItem{path: path, node: v, md: subMd})
69 }
70 } else if len(item.path) > 0 {
71
72 fm.Paths = append(fm.Paths, item.path)
73 }
74 }
75
76 return fm, nil
77 }
78
79
80 type fieldMaskPathItem struct {
81
82 path string
83
84
85 node interface{}
86
87
88 md *descriptor.DescriptorProto
89 }
90
View as plain text