blob: b3a0a76890c93be953aac7894ef51baadd1d8478 [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 Ong0b0f4032019-03-18 19:06:15 -070031 // If Indent is a non-empty string, it causes entries for an Array or Object
32 // to be preceded by the indent and trailed by a newline. Indent can only be
33 // composed of space or tab characters.
34 Indent string
35
36 // Resolver is the registry used for type lookups when marshaling
37 // google.protobuf.Any messages. If Resolver is not set, marshaling will
38 // default to using protoregistry.GlobalTypes.
39 Resolver *protoregistry.Types
Herbie Ong822de2d2019-03-27 13:16:23 -070040
41 encoder *json.Encoder
Herbie Ong7b828bc2019-02-08 19:56:24 -080042}
43
Herbie Ong0b0f4032019-03-18 19:06:15 -070044// Marshal marshals the given proto.Message in the JSON format using options in
45// MarshalOptions.
Herbie Ong7b828bc2019-02-08 19:56:24 -080046func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -070047 var err error
48 o.encoder, err = json.NewEncoder(o.Indent)
Herbie Ong87608a72019-03-06 14:32:24 -080049 if err != nil {
50 return nil, err
51 }
Herbie Ong822de2d2019-03-27 13:16:23 -070052 if o.Resolver == nil {
53 o.Resolver = protoregistry.GlobalTypes
54 }
Herbie Ong87608a72019-03-06 14:32:24 -080055
56 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -070057 err = o.marshalMessage(m.ProtoReflect())
Herbie Ong7b828bc2019-02-08 19:56:24 -080058 if !nerr.Merge(err) {
59 return nil, err
60 }
Herbie Ong822de2d2019-03-27 13:16:23 -070061 return o.encoder.Bytes(), nerr.E
Herbie Ong87608a72019-03-06 14:32:24 -080062}
63
64// marshalMessage marshals the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -070065func (o MarshalOptions) marshalMessage(m pref.Message) error {
Herbie Ong0b0f4032019-03-18 19:06:15 -070066 var nerr errors.NonFatal
67
68 if isCustomType(m.Type().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -070069 return o.marshalCustomType(m)
Herbie Ong0b0f4032019-03-18 19:06:15 -070070 }
71
Herbie Ong822de2d2019-03-27 13:16:23 -070072 o.encoder.StartObject()
73 defer o.encoder.EndObject()
74 if err := o.marshalFields(m); !nerr.Merge(err) {
Herbie Ong0b0f4032019-03-18 19:06:15 -070075 return err
76 }
Herbie Ong87608a72019-03-06 14:32:24 -080077
Herbie Ong0b0f4032019-03-18 19:06:15 -070078 return nerr.E
79}
80
81// marshalFields marshals the fields in the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -070082func (o MarshalOptions) marshalFields(m pref.Message) error {
Herbie Ong87608a72019-03-06 14:32:24 -080083 var nerr errors.NonFatal
84 fieldDescs := m.Type().Fields()
Herbie Ong7b828bc2019-02-08 19:56:24 -080085 knownFields := m.KnownFields()
Herbie Ong87608a72019-03-06 14:32:24 -080086
Herbie Ongf83d5bb2019-03-14 00:01:27 -070087 // Marshal out known fields.
Herbie Ong87608a72019-03-06 14:32:24 -080088 for i := 0; i < fieldDescs.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -080089 fd := fieldDescs.Get(i)
90 num := fd.Number()
91
92 if !knownFields.Has(num) {
93 if fd.Cardinality() == pref.Required {
94 // Treat unset required fields as a non-fatal error.
95 nerr.AppendRequiredNotSet(string(fd.FullName()))
96 }
97 continue
98 }
99
Herbie Ong87608a72019-03-06 14:32:24 -0800100 name := fd.JSONName()
Herbie Ong1c7462c2019-03-22 17:56:55 -0700101 val := knownFields.Get(num)
Herbie Ong822de2d2019-03-27 13:16:23 -0700102 if err := o.encoder.WriteName(name); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800103 return err
104 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700105 if err := o.marshalValue(val, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800106 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800107 }
108 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700109
110 // Marshal out extensions.
Herbie Ong822de2d2019-03-27 13:16:23 -0700111 if err := o.marshalExtensions(knownFields); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700112 return err
113 }
Herbie Ong87608a72019-03-06 14:32:24 -0800114 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800115}
116
Herbie Ong87608a72019-03-06 14:32:24 -0800117// marshalValue marshals the given protoreflect.Value.
Herbie Ong822de2d2019-03-27 13:16:23 -0700118func (o MarshalOptions) marshalValue(val pref.Value, fd pref.FieldDescriptor) error {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800119 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800120 if fd.Cardinality() == pref.Repeated {
121 // Map or repeated fields.
122 if fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700123 if err := o.marshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800124 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800125 }
126 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700127 if err := o.marshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800128 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800129 }
130 }
131 } else {
132 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700133 if err := o.marshalSingular(val, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800134 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800135 }
136 }
Herbie Ong87608a72019-03-06 14:32:24 -0800137 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800138}
139
Herbie Ong87608a72019-03-06 14:32:24 -0800140// marshalSingular marshals the given non-repeated field value. This includes
141// all scalar types, enums, messages, and groups.
Herbie Ong822de2d2019-03-27 13:16:23 -0700142func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error {
Herbie Ong87608a72019-03-06 14:32:24 -0800143 var nerr errors.NonFatal
144 switch kind := fd.Kind(); kind {
145 case pref.BoolKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700146 o.encoder.WriteBool(val.Bool())
Herbie Ong87608a72019-03-06 14:32:24 -0800147
148 case pref.StringKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700149 if err := o.encoder.WriteString(val.String()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800150 return err
151 }
152
153 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700154 o.encoder.WriteInt(val.Int())
Herbie Ong87608a72019-03-06 14:32:24 -0800155
156 case pref.Uint32Kind, pref.Fixed32Kind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700157 o.encoder.WriteUint(val.Uint())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800158
159 case pref.Int64Kind, pref.Sint64Kind, pref.Uint64Kind,
160 pref.Sfixed64Kind, pref.Fixed64Kind:
Herbie Ong87608a72019-03-06 14:32:24 -0800161 // 64-bit integers are written out as JSON string.
Herbie Ong822de2d2019-03-27 13:16:23 -0700162 o.encoder.WriteString(val.String())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800163
Herbie Ong87608a72019-03-06 14:32:24 -0800164 case pref.FloatKind:
165 // Encoder.WriteFloat handles the special numbers NaN and infinites.
Herbie Ong822de2d2019-03-27 13:16:23 -0700166 o.encoder.WriteFloat(val.Float(), 32)
Herbie Ong87608a72019-03-06 14:32:24 -0800167
168 case pref.DoubleKind:
169 // Encoder.WriteFloat handles the special numbers NaN and infinites.
Herbie Ong822de2d2019-03-27 13:16:23 -0700170 o.encoder.WriteFloat(val.Float(), 64)
Herbie Ong7b828bc2019-02-08 19:56:24 -0800171
172 case pref.BytesKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700173 err := o.encoder.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
Herbie Ong87608a72019-03-06 14:32:24 -0800174 if !nerr.Merge(err) {
175 return err
176 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800177
178 case pref.EnumKind:
Herbie Ong0b0f4032019-03-18 19:06:15 -0700179 enumType := fd.EnumType()
Herbie Ong7b828bc2019-02-08 19:56:24 -0800180 num := val.Enum()
Herbie Ong0b0f4032019-03-18 19:06:15 -0700181
182 if enumType.FullName() == "google.protobuf.NullValue" {
Herbie Ong822de2d2019-03-27 13:16:23 -0700183 o.encoder.WriteNull()
Herbie Ong0b0f4032019-03-18 19:06:15 -0700184 } else if desc := enumType.Values().ByNumber(num); desc != nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700185 err := o.encoder.WriteString(string(desc.Name()))
Herbie Ong87608a72019-03-06 14:32:24 -0800186 if !nerr.Merge(err) {
187 return err
188 }
189 } else {
190 // Use numeric value if there is no enum value descriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700191 o.encoder.WriteInt(int64(num))
Herbie Ong7b828bc2019-02-08 19:56:24 -0800192 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800193
194 case pref.MessageKind, pref.GroupKind:
Herbie Ong822de2d2019-03-27 13:16:23 -0700195 if err := o.marshalMessage(val.Message()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800196 return err
197 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800198
Herbie Ong87608a72019-03-06 14:32:24 -0800199 default:
Herbie Ong0b0f4032019-03-18 19:06:15 -0700200 panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
Herbie Ong87608a72019-03-06 14:32:24 -0800201 }
202 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800203}
204
Herbie Ong87608a72019-03-06 14:32:24 -0800205// marshalList marshals the given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700206func (o MarshalOptions) marshalList(list pref.List, fd pref.FieldDescriptor) error {
207 o.encoder.StartArray()
208 defer o.encoder.EndArray()
Herbie Ong87608a72019-03-06 14:32:24 -0800209
Herbie Ong7b828bc2019-02-08 19:56:24 -0800210 var nerr errors.NonFatal
Herbie Ong87608a72019-03-06 14:32:24 -0800211 for i := 0; i < list.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800212 item := list.Get(i)
Herbie Ong822de2d2019-03-27 13:16:23 -0700213 if err := o.marshalSingular(item, fd); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800214 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800215 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800216 }
Herbie Ong87608a72019-03-06 14:32:24 -0800217 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800218}
219
220type mapEntry struct {
221 key pref.MapKey
222 value pref.Value
223}
224
Herbie Ong87608a72019-03-06 14:32:24 -0800225// marshalMap marshals given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700226func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
227 o.encoder.StartObject()
228 defer o.encoder.EndObject()
Herbie Ong87608a72019-03-06 14:32:24 -0800229
Herbie Ong7b828bc2019-02-08 19:56:24 -0800230 msgFields := fd.MessageType().Fields()
231 keyType := msgFields.ByNumber(1)
232 valType := msgFields.ByNumber(2)
233
234 // Get a sorted list based on keyType first.
235 entries := make([]mapEntry, 0, mmap.Len())
236 mmap.Range(func(key pref.MapKey, val pref.Value) bool {
237 entries = append(entries, mapEntry{key: key, value: val})
238 return true
239 })
240 sortMap(keyType.Kind(), entries)
241
Herbie Ong87608a72019-03-06 14:32:24 -0800242 // Write out sorted list.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800243 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800244 for _, entry := range entries {
Herbie Ong822de2d2019-03-27 13:16:23 -0700245 if err := o.encoder.WriteName(entry.key.String()); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800246 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800247 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700248 if err := o.marshalSingular(entry.value, valType); !nerr.Merge(err) {
Herbie Ong87608a72019-03-06 14:32:24 -0800249 return err
250 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800251 }
Herbie Ong87608a72019-03-06 14:32:24 -0800252 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800253}
254
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700255// sortMap orders list based on value of key field for deterministic ordering.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800256func sortMap(keyKind pref.Kind, values []mapEntry) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700257 sort.Slice(values, func(i, j int) bool {
258 switch keyKind {
259 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind,
260 pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800261 return values[i].key.Int() < values[j].key.Int()
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700262
263 case pref.Uint32Kind, pref.Fixed32Kind,
264 pref.Uint64Kind, pref.Fixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800265 return values[i].key.Uint() < values[j].key.Uint()
266 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700267 return values[i].key.String() < values[j].key.String()
268 })
269}
270
271// marshalExtensions marshals extension fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700272func (o MarshalOptions) marshalExtensions(knownFields pref.KnownFields) error {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700273 type xtEntry struct {
274 key string
275 value pref.Value
276 xtType pref.ExtensionType
Herbie Ong7b828bc2019-02-08 19:56:24 -0800277 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700278
279 xtTypes := knownFields.ExtensionTypes()
280
281 // Get a sorted list based on field key first.
282 entries := make([]xtEntry, 0, xtTypes.Len())
283 xtTypes.Range(func(xt pref.ExtensionType) bool {
284 name := xt.FullName()
285 // If extended type is a MessageSet, set field name to be the message type name.
286 if isMessageSetExtension(xt) {
287 name = xt.MessageType().FullName()
288 }
289
290 num := xt.Number()
291 if knownFields.Has(num) {
292 // Use [name] format for JSON field name.
293 pval := knownFields.Get(num)
294 entries = append(entries, xtEntry{
295 key: string(name),
296 value: pval,
297 xtType: xt,
298 })
299 }
300 return true
301 })
302
303 // Sort extensions lexicographically.
304 sort.Slice(entries, func(i, j int) bool {
305 return entries[i].key < entries[j].key
306 })
307
308 // Write out sorted list.
309 var nerr errors.NonFatal
310 for _, entry := range entries {
311 // JSON field name is the proto field name enclosed in [], similar to
312 // textproto. This is consistent with Go v1 lib. C++ lib v3.7.0 does not
313 // marshal out extension fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700314 if err := o.encoder.WriteName("[" + entry.key + "]"); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700315 return err
316 }
Herbie Ong822de2d2019-03-27 13:16:23 -0700317 if err := o.marshalValue(entry.value, entry.xtType); !nerr.Merge(err) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700318 return err
319 }
320 }
321 return nerr.E
322}
323
324// isMessageSetExtension reports whether extension extends a message set.
325func isMessageSetExtension(xt pref.ExtensionType) bool {
326 if xt.Name() != "message_set_extension" {
327 return false
328 }
329 mt := xt.MessageType()
330 if mt == nil {
331 return false
332 }
333 if xt.FullName().Parent() != mt.FullName() {
334 return false
335 }
336 xmt := xt.ExtendedType()
337 if xmt.Fields().Len() != 0 {
338 return false
339 }
340 opt := xmt.Options().(*descpb.MessageOptions)
341 if opt == nil {
342 return false
343 }
344 return opt.GetMessageSetWireFormat()
Herbie Ong7b828bc2019-02-08 19:56:24 -0800345}