1
2
3
4
5 package protojson
6
7 import (
8 "encoding/base64"
9 "fmt"
10
11 "google.golang.org/protobuf/internal/encoding/json"
12 "google.golang.org/protobuf/internal/encoding/messageset"
13 "google.golang.org/protobuf/internal/errors"
14 "google.golang.org/protobuf/internal/filedesc"
15 "google.golang.org/protobuf/internal/flags"
16 "google.golang.org/protobuf/internal/genid"
17 "google.golang.org/protobuf/internal/order"
18 "google.golang.org/protobuf/internal/pragma"
19 "google.golang.org/protobuf/proto"
20 "google.golang.org/protobuf/reflect/protoreflect"
21 "google.golang.org/protobuf/reflect/protoregistry"
22 )
23
24 const defaultIndent = " "
25
26
27
28
29
30 func Format(m proto.Message) string {
31 return MarshalOptions{Multiline: true}.Format(m)
32 }
33
34
35
36
37 func Marshal(m proto.Message) ([]byte, error) {
38 return MarshalOptions{}.Marshal(m)
39 }
40
41
42 type MarshalOptions struct {
43 pragma.NoUnkeyedLiterals
44
45
46
47
48 Multiline bool
49
50
51
52
53
54 Indent string
55
56
57
58
59 AllowPartial bool
60
61
62
63 UseProtoNames bool
64
65
66 UseEnumNumbers bool
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 EmitUnpopulated bool
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 EmitDefaultValues bool
102
103
104
105 Resolver interface {
106 protoregistry.ExtensionTypeResolver
107 protoregistry.MessageTypeResolver
108 }
109 }
110
111
112
113
114
115 func (o MarshalOptions) Format(m proto.Message) string {
116 if m == nil || !m.ProtoReflect().IsValid() {
117 return "<nil>"
118 }
119 o.AllowPartial = true
120 b, _ := o.Marshal(m)
121 return string(b)
122 }
123
124
125
126
127 func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
128 return o.marshal(nil, m)
129 }
130
131
132
133 func (o MarshalOptions) MarshalAppend(b []byte, m proto.Message) ([]byte, error) {
134 return o.marshal(b, m)
135 }
136
137
138
139
140 func (o MarshalOptions) marshal(b []byte, m proto.Message) ([]byte, error) {
141 if o.Multiline && o.Indent == "" {
142 o.Indent = defaultIndent
143 }
144 if o.Resolver == nil {
145 o.Resolver = protoregistry.GlobalTypes
146 }
147
148 internalEnc, err := json.NewEncoder(b, o.Indent)
149 if err != nil {
150 return nil, err
151 }
152
153
154
155 if m == nil {
156 return append(b, '{', '}'), nil
157 }
158
159 enc := encoder{internalEnc, o}
160 if err := enc.marshalMessage(m.ProtoReflect(), ""); err != nil {
161 return nil, err
162 }
163 if o.AllowPartial {
164 return enc.Bytes(), nil
165 }
166 return enc.Bytes(), proto.CheckInitialized(m)
167 }
168
169 type encoder struct {
170 *json.Encoder
171 opts MarshalOptions
172 }
173
174
175 var typeFieldDesc = func() protoreflect.FieldDescriptor {
176 var fd filedesc.Field
177 fd.L0.FullName = "@type"
178 fd.L0.Index = -1
179 fd.L1.Cardinality = protoreflect.Optional
180 fd.L1.Kind = protoreflect.StringKind
181 return &fd
182 }()
183
184
185
186 type typeURLFieldRanger struct {
187 order.FieldRanger
188 typeURL string
189 }
190
191 func (m typeURLFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
192 if !f(typeFieldDesc, protoreflect.ValueOfString(m.typeURL)) {
193 return
194 }
195 m.FieldRanger.Range(f)
196 }
197
198
199
200 type unpopulatedFieldRanger struct {
201 protoreflect.Message
202
203 skipNull bool
204 }
205
206 func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
207 fds := m.Descriptor().Fields()
208 for i := 0; i < fds.Len(); i++ {
209 fd := fds.Get(i)
210 if m.Has(fd) || fd.ContainingOneof() != nil {
211 continue
212 }
213
214 v := m.Get(fd)
215 isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid()
216 isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil
217 if isProto2Scalar || isSingularMessage {
218 if m.skipNull {
219 continue
220 }
221 v = protoreflect.Value{}
222 }
223 if !f(fd, v) {
224 return
225 }
226 }
227 m.Message.Range(f)
228 }
229
230
231
232
233 func (e encoder) marshalMessage(m protoreflect.Message, typeURL string) error {
234 if !flags.ProtoLegacy && messageset.IsMessageSet(m.Descriptor()) {
235 return errors.New("no support for proto1 MessageSets")
236 }
237
238 if marshal := wellKnownTypeMarshaler(m.Descriptor().FullName()); marshal != nil {
239 return marshal(e, m)
240 }
241
242 e.StartObject()
243 defer e.EndObject()
244
245 var fields order.FieldRanger = m
246 switch {
247 case e.opts.EmitUnpopulated:
248 fields = unpopulatedFieldRanger{Message: m, skipNull: false}
249 case e.opts.EmitDefaultValues:
250 fields = unpopulatedFieldRanger{Message: m, skipNull: true}
251 }
252 if typeURL != "" {
253 fields = typeURLFieldRanger{fields, typeURL}
254 }
255
256 var err error
257 order.RangeFields(fields, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
258 name := fd.JSONName()
259 if e.opts.UseProtoNames {
260 name = fd.TextName()
261 }
262
263 if err = e.WriteName(name); err != nil {
264 return false
265 }
266 if err = e.marshalValue(v, fd); err != nil {
267 return false
268 }
269 return true
270 })
271 return err
272 }
273
274
275 func (e encoder) marshalValue(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
276 switch {
277 case fd.IsList():
278 return e.marshalList(val.List(), fd)
279 case fd.IsMap():
280 return e.marshalMap(val.Map(), fd)
281 default:
282 return e.marshalSingular(val, fd)
283 }
284 }
285
286
287
288 func (e encoder) marshalSingular(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
289 if !val.IsValid() {
290 e.WriteNull()
291 return nil
292 }
293
294 switch kind := fd.Kind(); kind {
295 case protoreflect.BoolKind:
296 e.WriteBool(val.Bool())
297
298 case protoreflect.StringKind:
299 if e.WriteString(val.String()) != nil {
300 return errors.InvalidUTF8(string(fd.FullName()))
301 }
302
303 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
304 e.WriteInt(val.Int())
305
306 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
307 e.WriteUint(val.Uint())
308
309 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind,
310 protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind:
311
312 e.WriteString(val.String())
313
314 case protoreflect.FloatKind:
315
316 e.WriteFloat(val.Float(), 32)
317
318 case protoreflect.DoubleKind:
319
320 e.WriteFloat(val.Float(), 64)
321
322 case protoreflect.BytesKind:
323 e.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
324
325 case protoreflect.EnumKind:
326 if fd.Enum().FullName() == genid.NullValue_enum_fullname {
327 e.WriteNull()
328 } else {
329 desc := fd.Enum().Values().ByNumber(val.Enum())
330 if e.opts.UseEnumNumbers || desc == nil {
331 e.WriteInt(int64(val.Enum()))
332 } else {
333 e.WriteString(string(desc.Name()))
334 }
335 }
336
337 case protoreflect.MessageKind, protoreflect.GroupKind:
338 if err := e.marshalMessage(val.Message(), ""); err != nil {
339 return err
340 }
341
342 default:
343 panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
344 }
345 return nil
346 }
347
348
349 func (e encoder) marshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error {
350 e.StartArray()
351 defer e.EndArray()
352
353 for i := 0; i < list.Len(); i++ {
354 item := list.Get(i)
355 if err := e.marshalSingular(item, fd); err != nil {
356 return err
357 }
358 }
359 return nil
360 }
361
362
363 func (e encoder) marshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error {
364 e.StartObject()
365 defer e.EndObject()
366
367 var err error
368 order.RangeEntries(mmap, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
369 if err = e.WriteName(k.String()); err != nil {
370 return false
371 }
372 if err = e.marshalSingular(v, fd.MapValue()); err != nil {
373 return false
374 }
375 return true
376 })
377 return err
378 }
379
View as plain text