blob: 8e25183b9953a7db81857d1b851714ef0589532c [file] [log] [blame]
Herbie Ong7b828bc2019-02-08 19:56:24 -08001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package jsonpb
6
7import (
8 "encoding/base64"
Herbie Ong0b0f4032019-03-18 19:06:15 -07009 "fmt"
Herbie Ong7b828bc2019-02-08 19:56:24 -080010 "sort"
11
Herbie Ong87608a72019-03-06 14:32:24 -080012 "github.com/golang/protobuf/v2/internal/encoding/json"
Herbie Ong7b828bc2019-02-08 19:56:24 -080013 "github.com/golang/protobuf/v2/internal/errors"
14 "github.com/golang/protobuf/v2/internal/pragma"
15 "github.com/golang/protobuf/v2/proto"
16 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Ong0b0f4032019-03-18 19:06:15 -070017 "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ongf83d5bb2019-03-14 00:01:27 -070018
19 descpb "github.com/golang/protobuf/v2/types/descriptor"
Herbie Ong7b828bc2019-02-08 19:56:24 -080020)
21
22// Marshal writes the given proto.Message in JSON format using default options.
23func Marshal(m proto.Message) ([]byte, error) {
24 return MarshalOptions{}.Marshal(m)
25}
26
27// MarshalOptions is a configurable JSON format marshaler.
28type MarshalOptions struct {
29 pragma.NoUnkeyedLiterals
30
Herbie Ong329be5b2019-03-27 14:47:59 -070031 // AllowPartial allows messages that have missing required fields to marshal
32 // without returning an error. If AllowPartial is false (the default),
33 // Marshal will return error if there are any missing required fields.
34 AllowPartial bool
35
Herbie Ong0b0f4032019-03-18 19:06:15 -070036 // If Indent is a non-empty string, it causes entries for an Array or Object
37 // to be preceded by the indent and trailed by a newline. Indent can only be
38 // composed of space or tab characters.
39 Indent string
40
41 // Resolver is the registry used for type lookups when marshaling
42 // google.protobuf.Any messages. If Resolver is not set, marshaling will
43 // default to using protoregistry.GlobalTypes.
44 Resolver *protoregistry.Types
Herbie Ong822de2d2019-03-27 13:16:23 -070045
46 encoder *json.Encoder
Herbie Ong7b828bc2019-02-08 19:56:24 -080047}
48
Herbie Ong0b0f4032019-03-18 19:06:15 -070049// Marshal marshals the given proto.Message in the JSON format using options in
50// MarshalOptions.
Herbie Ong7b828bc2019-02-08 19:56:24 -080051func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -070052 var err error
53 o.encoder, err = json.NewEncoder(o.Indent)
Herbie Ong87608a72019-03-06 14:32:24 -080054 if err != nil {
55 return nil, err
56 }
Herbie Ong822de2d2019-03-27 13:16:23 -070057 if o.Resolver == nil {
58 o.Resolver = protoregistry.GlobalTypes
59 }
Herbie Ong87608a72019-03-06 14:32:24 -080060
61 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -070062 err = o.marshalMessage(m.ProtoReflect())
Herbie Ong7b828bc2019-02-08 19:56:24 -080063 if !nerr.Merge(err) {
64 return nil, err
65 }
Herbie Ong822de2d2019-03-27 13:16:23 -070066 return o.encoder.Bytes(), nerr.E
Herbie Ong87608a72019-03-06 14:32:24 -080067}
68
69// marshalMessage marshals the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -070070func (o MarshalOptions) marshalMessage(m pref.Message) error {
Herbie Ong0b0f4032019-03-18 19:06:15 -070071 var nerr errors.NonFatal
72
73 if isCustomType(m.Type().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -070074 return o.marshalCustomType(m)
Herbie Ong0b0f4032019-03-18 19:06:15 -070075 }
76
Herbie Ong822de2d2019-03-27 13:16:23 -070077 o.encoder.StartObject()
78 defer o.encoder.EndObject()
79 if err := o.marshalFields(m); !nerr.Merge(err) {
Herbie Ong0b0f4032019-03-18 19:06:15 -070080 return err
81 }
Herbie Ong87608a72019-03-06 14:32:24 -080082
Herbie Ong0b0f4032019-03-18 19:06:15 -070083 return nerr.E
84}
85
86// marshalFields marshals the fields in the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -070087func (o MarshalOptions) marshalFields(m pref.Message) error {
Herbie Ong87608a72019-03-06 14:32:24 -080088 var nerr errors.NonFatal
89 fieldDescs := m.Type().Fields()
Herbie Ong7b828bc2019-02-08 19:56:24 -080090 knownFields := m.KnownFields()
Herbie Ong87608a72019-03-06 14:32:24 -080091
Herbie Ongf83d5bb2019-03-14 00:01:27 -070092 // Marshal out known fields.
Herbie Ong87608a72019-03-06 14:32:24 -080093 for i := 0; i < fieldDescs.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -080094 fd := fieldDescs.Get(i)
95 num := fd.Number()
96
97 if !knownFields.Has(num) {
Herbie Ong329be5b2019-03-27 14:47:59 -070098 if !o.AllowPartial && fd.Cardinality() == pref.Required {
Herbie Ong7b828bc2019-02-08 19:56:24 -080099 // Treat unset required fields as a non-fatal error.
100 nerr.AppendRequiredNotSet(string(fd.FullName()))
101 }
102 continue
103 }
104
Herbie Ong87608a72019-03-06 14:32:24 -0800105 name := fd.JSONName()
Herbie Ong1c7462c2019-03-22 17:56:55 -0700106 val := knownFields.Get(num)
Herbie Ong822de2d2019-03-27 13:16:23 -0700107 if err := o.encoder.WriteName(name); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800108 return err
109 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700110 if err := o.marshalValue(val, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800111 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800112 }
113 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700114
115 // Marshal out extensions.
Herbie Ong822de2d2019-03-27 13:16:23 -0700116 if err := o.marshalExtensions(knownFields); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700117 return err
118 }
Herbie Ong87608a72019-03-06 14:32:24 -0800119 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800120}
121
Herbie Ong87608a72019-03-06 14:32:24 -0800122// marshalValue marshals the given protoreflect.Value.
Herbie Ong822de2d2019-03-27 13:16:23 -0700123func (o MarshalOptions) marshalValue(val pref.Value, fd pref.FieldDescriptor) error {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800124 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800125 if fd.Cardinality() == pref.Repeated {
126 // Map or repeated fields.
127 if fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700128 if err := o.marshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800129 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800130 }
131 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700132 if err := o.marshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800133 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800134 }
135 }
136 } else {
137 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700138 if err := o.marshalSingular(val, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800139 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800140 }
141 }
Herbie Ong87608a72019-03-06 14:32:24 -0800142 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800143}
144
Herbie Ong87608a72019-03-06 14:32:24 -0800145// marshalSingular marshals the given non-repeated field value. This includes
146// all scalar types, enums, messages, and groups.
Herbie Ong822de2d2019-03-27 13:16:23 -0700147func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error {
Herbie Ong87608a72019-03-06 14:32:24 -0800148 var nerr errors.NonFatal
149 switch kind := fd.Kind(); kind {
150 case pref.BoolKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700151 o.encoder.WriteBool(val.Bool())
Herbie Ong87608a72019-03-06 14:32:24 -0800152
153 case pref.StringKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700154 if err := o.encoder.WriteString(val.String()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800155 return err
156 }
157
158 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700159 o.encoder.WriteInt(val.Int())
Herbie Ong87608a72019-03-06 14:32:24 -0800160
161 case pref.Uint32Kind, pref.Fixed32Kind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700162 o.encoder.WriteUint(val.Uint())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800163
164 case pref.Int64Kind, pref.Sint64Kind, pref.Uint64Kind,
165 pref.Sfixed64Kind, pref.Fixed64Kind:
Herbie Ong87608a72019-03-06 14:32:24 -0800166 // 64-bit integers are written out as JSON string.
Herbie Ong822de2d2019-03-27 13:16:23 -0700167 o.encoder.WriteString(val.String())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800168
Herbie Ong87608a72019-03-06 14:32:24 -0800169 case pref.FloatKind:
170 // Encoder.WriteFloat handles the special numbers NaN and infinites.
Herbie Ong822de2d2019-03-27 13:16:23 -0700171 o.encoder.WriteFloat(val.Float(), 32)
Herbie Ong87608a72019-03-06 14:32:24 -0800172
173 case pref.DoubleKind:
174 // Encoder.WriteFloat handles the special numbers NaN and infinites.
Herbie Ong822de2d2019-03-27 13:16:23 -0700175 o.encoder.WriteFloat(val.Float(), 64)
Herbie Ong7b828bc2019-02-08 19:56:24 -0800176
177 case pref.BytesKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700178 err := o.encoder.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
Herbie Ong87608a72019-03-06 14:32:24 -0800179 if !nerr.Merge(err) {
180 return err
181 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800182
183 case pref.EnumKind:
Herbie Ong0b0f4032019-03-18 19:06:15 -0700184 enumType := fd.EnumType()
Herbie Ong7b828bc2019-02-08 19:56:24 -0800185 num := val.Enum()
Herbie Ong0b0f4032019-03-18 19:06:15 -0700186
187 if enumType.FullName() == "google.protobuf.NullValue" {
Herbie Ong822de2d2019-03-27 13:16:23 -0700188 o.encoder.WriteNull()
Herbie Ong0b0f4032019-03-18 19:06:15 -0700189 } else if desc := enumType.Values().ByNumber(num); desc != nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700190 err := o.encoder.WriteString(string(desc.Name()))
Herbie Ong87608a72019-03-06 14:32:24 -0800191 if !nerr.Merge(err) {
192 return err
193 }
194 } else {
195 // Use numeric value if there is no enum value descriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700196 o.encoder.WriteInt(int64(num))
Herbie Ong7b828bc2019-02-08 19:56:24 -0800197 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800198
199 case pref.MessageKind, pref.GroupKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700200 if err := o.marshalMessage(val.Message()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800201 return err
202 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800203
Herbie Ong87608a72019-03-06 14:32:24 -0800204 default:
Herbie Ong0b0f4032019-03-18 19:06:15 -0700205 panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
Herbie Ong87608a72019-03-06 14:32:24 -0800206 }
207 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800208}
209
Herbie Ong87608a72019-03-06 14:32:24 -0800210// marshalList marshals the given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700211func (o MarshalOptions) marshalList(list pref.List, fd pref.FieldDescriptor) error {
212 o.encoder.StartArray()
213 defer o.encoder.EndArray()
Herbie Ong87608a72019-03-06 14:32:24 -0800214
Herbie Ong7b828bc2019-02-08 19:56:24 -0800215 var nerr errors.NonFatal
Herbie Ong87608a72019-03-06 14:32:24 -0800216 for i := 0; i < list.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800217 item := list.Get(i)
Herbie Ong822de2d2019-03-27 13:16:23 -0700218 if err := o.marshalSingular(item, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800219 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800220 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800221 }
Herbie Ong87608a72019-03-06 14:32:24 -0800222 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800223}
224
225type mapEntry struct {
226 key pref.MapKey
227 value pref.Value
228}
229
Herbie Ong87608a72019-03-06 14:32:24 -0800230// marshalMap marshals given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700231func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
232 o.encoder.StartObject()
233 defer o.encoder.EndObject()
Herbie Ong87608a72019-03-06 14:32:24 -0800234
Herbie Ong7b828bc2019-02-08 19:56:24 -0800235 msgFields := fd.MessageType().Fields()
236 keyType := msgFields.ByNumber(1)
237 valType := msgFields.ByNumber(2)
238
239 // Get a sorted list based on keyType first.
240 entries := make([]mapEntry, 0, mmap.Len())
241 mmap.Range(func(key pref.MapKey, val pref.Value) bool {
242 entries = append(entries, mapEntry{key: key, value: val})
243 return true
244 })
245 sortMap(keyType.Kind(), entries)
246
Herbie Ong87608a72019-03-06 14:32:24 -0800247 // Write out sorted list.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800248 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800249 for _, entry := range entries {
Herbie Ong822de2d2019-03-27 13:16:23 -0700250 if err := o.encoder.WriteName(entry.key.String()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800251 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800252 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700253 if err := o.marshalSingular(entry.value, valType); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800254 return err
255 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800256 }
Herbie Ong87608a72019-03-06 14:32:24 -0800257 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800258}
259
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700260// sortMap orders list based on value of key field for deterministic ordering.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800261func sortMap(keyKind pref.Kind, values []mapEntry) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700262 sort.Slice(values, func(i, j int) bool {
263 switch keyKind {
264 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind,
265 pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800266 return values[i].key.Int() < values[j].key.Int()
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700267
268 case pref.Uint32Kind, pref.Fixed32Kind,
269 pref.Uint64Kind, pref.Fixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800270 return values[i].key.Uint() < values[j].key.Uint()
271 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700272 return values[i].key.String() < values[j].key.String()
273 })
274}
275
276// marshalExtensions marshals extension fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700277func (o MarshalOptions) marshalExtensions(knownFields pref.KnownFields) error {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700278 type xtEntry struct {
279 key string
280 value pref.Value
281 xtType pref.ExtensionType
Herbie Ong7b828bc2019-02-08 19:56:24 -0800282 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700283
284 xtTypes := knownFields.ExtensionTypes()
285
286 // Get a sorted list based on field key first.
287 entries := make([]xtEntry, 0, xtTypes.Len())
288 xtTypes.Range(func(xt pref.ExtensionType) bool {
289 name := xt.FullName()
290 // If extended type is a MessageSet, set field name to be the message type name.
291 if isMessageSetExtension(xt) {
292 name = xt.MessageType().FullName()
293 }
294
295 num := xt.Number()
296 if knownFields.Has(num) {
297 // Use [name] format for JSON field name.
298 pval := knownFields.Get(num)
299 entries = append(entries, xtEntry{
300 key: string(name),
301 value: pval,
302 xtType: xt,
303 })
304 }
305 return true
306 })
307
308 // Sort extensions lexicographically.
309 sort.Slice(entries, func(i, j int) bool {
310 return entries[i].key < entries[j].key
311 })
312
313 // Write out sorted list.
314 var nerr errors.NonFatal
315 for _, entry := range entries {
316 // JSON field name is the proto field name enclosed in [], similar to
317 // textproto. This is consistent with Go v1 lib. C++ lib v3.7.0 does not
318 // marshal out extension fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700319 if err := o.encoder.WriteName("[" + entry.key + "]"); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700320 return err
321 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700322 if err := o.marshalValue(entry.value, entry.xtType); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700323 return err
324 }
325 }
326 return nerr.E
327}
328
329// isMessageSetExtension reports whether extension extends a message set.
330func isMessageSetExtension(xt pref.ExtensionType) bool {
331 if xt.Name() != "message_set_extension" {
332 return false
333 }
334 mt := xt.MessageType()
335 if mt == nil {
336 return false
337 }
338 if xt.FullName().Parent() != mt.FullName() {
339 return false
340 }
341 xmt := xt.ExtendedType()
342 if xmt.Fields().Len() != 0 {
343 return false
344 }
345 opt := xmt.Options().(*descpb.MessageOptions)
346 if opt == nil {
347 return false
348 }
349 return opt.GetMessageSetWireFormat()
Herbie Ong7b828bc2019-02-08 19:56:24 -0800350}