blob: 3830f31dbbf3ccd6436eb9b7ce6c48291a77c3a3 [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 Ong7b828bc2019-02-08 19:56:24 -08009 "sort"
10
Herbie Ong87608a72019-03-06 14:32:24 -080011 "github.com/golang/protobuf/v2/internal/encoding/json"
Herbie Ong7b828bc2019-02-08 19:56:24 -080012 "github.com/golang/protobuf/v2/internal/errors"
13 "github.com/golang/protobuf/v2/internal/pragma"
14 "github.com/golang/protobuf/v2/proto"
15 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Ongf83d5bb2019-03-14 00:01:27 -070016
17 descpb "github.com/golang/protobuf/v2/types/descriptor"
Herbie Ong7b828bc2019-02-08 19:56:24 -080018)
19
20// Marshal writes the given proto.Message in JSON format using default options.
21func Marshal(m proto.Message) ([]byte, error) {
22 return MarshalOptions{}.Marshal(m)
23}
24
25// MarshalOptions is a configurable JSON format marshaler.
26type MarshalOptions struct {
27 pragma.NoUnkeyedLiterals
28
29 // Set Compact to true to have output in a single line with no line breaks.
30 Compact bool
31}
32
Herbie Ong87608a72019-03-06 14:32:24 -080033// Marshal returns the given proto.Message in JSON format using options in MarshalOptions object.
Herbie Ong7b828bc2019-02-08 19:56:24 -080034func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
Herbie Ong7b828bc2019-02-08 19:56:24 -080035 indent := " "
36 if o.Compact {
37 indent = ""
38 }
39
Herbie Ong87608a72019-03-06 14:32:24 -080040 enc, err := newEncoder(indent)
41 if err != nil {
42 return nil, err
43 }
44
45 var nerr errors.NonFatal
46 err = enc.marshalMessage(m.ProtoReflect())
Herbie Ong7b828bc2019-02-08 19:56:24 -080047 if !nerr.Merge(err) {
48 return nil, err
49 }
Herbie Ong87608a72019-03-06 14:32:24 -080050 return enc.Bytes(), nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -080051}
52
Herbie Ong87608a72019-03-06 14:32:24 -080053// encoder encodes protoreflect values into JSON.
54type encoder struct {
55 *json.Encoder
56}
Herbie Ong7b828bc2019-02-08 19:56:24 -080057
Herbie Ong87608a72019-03-06 14:32:24 -080058func newEncoder(indent string) (encoder, error) {
59 enc, err := json.NewEncoder(indent)
60 if err != nil {
61 return encoder{}, errors.New("error in constructing an encoder: %v", err)
62 }
63 return encoder{enc}, nil
64}
65
66// marshalMessage marshals the given protoreflect.Message.
67func (e encoder) marshalMessage(m pref.Message) error {
68 e.StartObject()
69 defer e.EndObject()
70
71 var nerr errors.NonFatal
72 fieldDescs := m.Type().Fields()
Herbie Ong7b828bc2019-02-08 19:56:24 -080073 knownFields := m.KnownFields()
Herbie Ong87608a72019-03-06 14:32:24 -080074
Herbie Ongf83d5bb2019-03-14 00:01:27 -070075 // Marshal out known fields.
Herbie Ong87608a72019-03-06 14:32:24 -080076 for i := 0; i < fieldDescs.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -080077 fd := fieldDescs.Get(i)
78 num := fd.Number()
79
80 if !knownFields.Has(num) {
81 if fd.Cardinality() == pref.Required {
82 // Treat unset required fields as a non-fatal error.
83 nerr.AppendRequiredNotSet(string(fd.FullName()))
84 }
85 continue
86 }
87
Herbie Ong87608a72019-03-06 14:32:24 -080088 name := fd.JSONName()
89 if err := e.WriteName(name); !nerr.Merge(err) {
90 return err
91 }
92
93 val := knownFields.Get(num)
94 if err := e.marshalValue(val, fd); !nerr.Merge(err) {
95 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -080096 }
97 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -070098
99 // Marshal out extensions.
100 if err := e.marshalExtensions(knownFields); !nerr.Merge(err) {
101 return err
102 }
Herbie Ong87608a72019-03-06 14:32:24 -0800103 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800104}
105
Herbie Ong87608a72019-03-06 14:32:24 -0800106// marshalValue marshals the given protoreflect.Value.
107func (e encoder) marshalValue(val pref.Value, fd pref.FieldDescriptor) error {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800108 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800109 if fd.Cardinality() == pref.Repeated {
110 // Map or repeated fields.
111 if fd.IsMap() {
Herbie Ong87608a72019-03-06 14:32:24 -0800112 if err := e.marshalMap(val.Map(), fd); !nerr.Merge(err) {
113 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800114 }
115 } else {
Herbie Ong87608a72019-03-06 14:32:24 -0800116 if err := e.marshalList(val.List(), fd); !nerr.Merge(err) {
117 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800118 }
119 }
120 } else {
121 // Required or optional fields.
Herbie Ong87608a72019-03-06 14:32:24 -0800122 if err := e.marshalSingular(val, fd); !nerr.Merge(err) {
123 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800124 }
125 }
Herbie Ong87608a72019-03-06 14:32:24 -0800126 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800127}
128
Herbie Ong87608a72019-03-06 14:32:24 -0800129// marshalSingular marshals the given non-repeated field value. This includes
130// all scalar types, enums, messages, and groups.
131func (e encoder) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error {
132 var nerr errors.NonFatal
133 switch kind := fd.Kind(); kind {
134 case pref.BoolKind:
135 e.WriteBool(val.Bool())
136
137 case pref.StringKind:
138 if err := e.WriteString(val.String()); !nerr.Merge(err) {
139 return err
140 }
141
142 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
143 e.WriteInt(val.Int())
144
145 case pref.Uint32Kind, pref.Fixed32Kind:
146 e.WriteUint(val.Uint())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800147
148 case pref.Int64Kind, pref.Sint64Kind, pref.Uint64Kind,
149 pref.Sfixed64Kind, pref.Fixed64Kind:
Herbie Ong87608a72019-03-06 14:32:24 -0800150 // 64-bit integers are written out as JSON string.
151 e.WriteString(val.String())
Herbie Ong7b828bc2019-02-08 19:56:24 -0800152
Herbie Ong87608a72019-03-06 14:32:24 -0800153 case pref.FloatKind:
154 // Encoder.WriteFloat handles the special numbers NaN and infinites.
155 e.WriteFloat(val.Float(), 32)
156
157 case pref.DoubleKind:
158 // Encoder.WriteFloat handles the special numbers NaN and infinites.
159 e.WriteFloat(val.Float(), 64)
Herbie Ong7b828bc2019-02-08 19:56:24 -0800160
161 case pref.BytesKind:
Herbie Ong87608a72019-03-06 14:32:24 -0800162 err := e.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
163 if !nerr.Merge(err) {
164 return err
165 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800166
167 case pref.EnumKind:
168 num := val.Enum()
169 if desc := fd.EnumType().Values().ByNumber(num); desc != nil {
Herbie Ong87608a72019-03-06 14:32:24 -0800170 err := e.WriteString(string(desc.Name()))
171 if !nerr.Merge(err) {
172 return err
173 }
174 } else {
175 // Use numeric value if there is no enum value descriptor.
176 e.WriteInt(int64(num))
Herbie Ong7b828bc2019-02-08 19:56:24 -0800177 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800178
179 case pref.MessageKind, pref.GroupKind:
Herbie Ong87608a72019-03-06 14:32:24 -0800180 if err := e.marshalMessage(val.Message()); !nerr.Merge(err) {
181 return err
182 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800183
Herbie Ong87608a72019-03-06 14:32:24 -0800184 default:
185 return errors.New("%v has unknown kind: %v", fd.FullName(), kind)
186 }
187 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800188}
189
Herbie Ong87608a72019-03-06 14:32:24 -0800190// marshalList marshals the given protoreflect.List.
191func (e encoder) marshalList(list pref.List, fd pref.FieldDescriptor) error {
192 e.StartArray()
193 defer e.EndArray()
194
Herbie Ong7b828bc2019-02-08 19:56:24 -0800195 var nerr errors.NonFatal
Herbie Ong87608a72019-03-06 14:32:24 -0800196 for i := 0; i < list.Len(); i++ {
Herbie Ong7b828bc2019-02-08 19:56:24 -0800197 item := list.Get(i)
Herbie Ong87608a72019-03-06 14:32:24 -0800198 if err := e.marshalSingular(item, fd); !nerr.Merge(err) {
199 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800200 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800201 }
Herbie Ong87608a72019-03-06 14:32:24 -0800202 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800203}
204
205type mapEntry struct {
206 key pref.MapKey
207 value pref.Value
208}
209
Herbie Ong87608a72019-03-06 14:32:24 -0800210// marshalMap marshals given protoreflect.Map.
211func (e encoder) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
212 e.StartObject()
213 defer e.EndObject()
214
Herbie Ong7b828bc2019-02-08 19:56:24 -0800215 msgFields := fd.MessageType().Fields()
216 keyType := msgFields.ByNumber(1)
217 valType := msgFields.ByNumber(2)
218
219 // Get a sorted list based on keyType first.
220 entries := make([]mapEntry, 0, mmap.Len())
221 mmap.Range(func(key pref.MapKey, val pref.Value) bool {
222 entries = append(entries, mapEntry{key: key, value: val})
223 return true
224 })
225 sortMap(keyType.Kind(), entries)
226
Herbie Ong87608a72019-03-06 14:32:24 -0800227 // Write out sorted list.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800228 var nerr errors.NonFatal
Herbie Ong7b828bc2019-02-08 19:56:24 -0800229 for _, entry := range entries {
Herbie Ong87608a72019-03-06 14:32:24 -0800230 if err := e.WriteName(entry.key.String()); !nerr.Merge(err) {
231 return err
Herbie Ong7b828bc2019-02-08 19:56:24 -0800232 }
Herbie Ong87608a72019-03-06 14:32:24 -0800233 if err := e.marshalSingular(entry.value, valType); !nerr.Merge(err) {
234 return err
235 }
Herbie Ong7b828bc2019-02-08 19:56:24 -0800236 }
Herbie Ong87608a72019-03-06 14:32:24 -0800237 return nerr.E
Herbie Ong7b828bc2019-02-08 19:56:24 -0800238}
239
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700240// sortMap orders list based on value of key field for deterministic ordering.
Herbie Ong7b828bc2019-02-08 19:56:24 -0800241func sortMap(keyKind pref.Kind, values []mapEntry) {
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700242 sort.Slice(values, func(i, j int) bool {
243 switch keyKind {
244 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind,
245 pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800246 return values[i].key.Int() < values[j].key.Int()
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700247
248 case pref.Uint32Kind, pref.Fixed32Kind,
249 pref.Uint64Kind, pref.Fixed64Kind:
Herbie Ong7b828bc2019-02-08 19:56:24 -0800250 return values[i].key.Uint() < values[j].key.Uint()
251 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700252 return values[i].key.String() < values[j].key.String()
253 })
254}
255
256// marshalExtensions marshals extension fields.
257func (e encoder) marshalExtensions(knownFields pref.KnownFields) error {
258 type xtEntry struct {
259 key string
260 value pref.Value
261 xtType pref.ExtensionType
Herbie Ong7b828bc2019-02-08 19:56:24 -0800262 }
Herbie Ongf83d5bb2019-03-14 00:01:27 -0700263
264 xtTypes := knownFields.ExtensionTypes()
265
266 // Get a sorted list based on field key first.
267 entries := make([]xtEntry, 0, xtTypes.Len())
268 xtTypes.Range(func(xt pref.ExtensionType) bool {
269 name := xt.FullName()
270 // If extended type is a MessageSet, set field name to be the message type name.
271 if isMessageSetExtension(xt) {
272 name = xt.MessageType().FullName()
273 }
274
275 num := xt.Number()
276 if knownFields.Has(num) {
277 // Use [name] format for JSON field name.
278 pval := knownFields.Get(num)
279 entries = append(entries, xtEntry{
280 key: string(name),
281 value: pval,
282 xtType: xt,
283 })
284 }
285 return true
286 })
287
288 // Sort extensions lexicographically.
289 sort.Slice(entries, func(i, j int) bool {
290 return entries[i].key < entries[j].key
291 })
292
293 // Write out sorted list.
294 var nerr errors.NonFatal
295 for _, entry := range entries {
296 // JSON field name is the proto field name enclosed in [], similar to
297 // textproto. This is consistent with Go v1 lib. C++ lib v3.7.0 does not
298 // marshal out extension fields.
299 if err := e.WriteName("[" + entry.key + "]"); !nerr.Merge(err) {
300 return err
301 }
302 if err := e.marshalValue(entry.value, entry.xtType); !nerr.Merge(err) {
303 return err
304 }
305 }
306 return nerr.E
307}
308
309// isMessageSetExtension reports whether extension extends a message set.
310func isMessageSetExtension(xt pref.ExtensionType) bool {
311 if xt.Name() != "message_set_extension" {
312 return false
313 }
314 mt := xt.MessageType()
315 if mt == nil {
316 return false
317 }
318 if xt.FullName().Parent() != mt.FullName() {
319 return false
320 }
321 xmt := xt.ExtendedType()
322 if xmt.Fields().Len() != 0 {
323 return false
324 }
325 opt := xmt.Options().(*descpb.MessageOptions)
326 if opt == nil {
327 return false
328 }
329 return opt.GetMessageSetWireFormat()
Herbie Ong7b828bc2019-02-08 19:56:24 -0800330}