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