blob: 4b0d9bbba5d44e3c3fca38e719bcb8ab759e3f3a [file] [log] [blame]
Herbie Ongc96a79d2019-03-08 10:49:17 -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"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13
14 "github.com/golang/protobuf/v2/internal/encoding/json"
15 "github.com/golang/protobuf/v2/internal/errors"
Herbie Onge52379a2019-03-15 18:00:19 -070016 "github.com/golang/protobuf/v2/internal/pragma"
Herbie Ongc96a79d2019-03-08 10:49:17 -080017 "github.com/golang/protobuf/v2/internal/set"
18 "github.com/golang/protobuf/v2/proto"
19 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Onge52379a2019-03-15 18:00:19 -070020 "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ongc96a79d2019-03-08 10:49:17 -080021)
22
23// Unmarshal reads the given []byte into the given proto.Message.
24func Unmarshal(m proto.Message, b []byte) error {
25 return UnmarshalOptions{}.Unmarshal(m, b)
26}
27
28// UnmarshalOptions is a configurable JSON format parser.
Herbie Onge52379a2019-03-15 18:00:19 -070029type UnmarshalOptions struct {
30 pragma.NoUnkeyedLiterals
31
Herbie Ong329be5b2019-03-27 14:47:59 -070032 // AllowPartial accepts input for messages that will result in missing
33 // required fields. If AllowPartial is false (the default), Unmarshal will
34 // return error if there are any missing required fields.
35 AllowPartial bool
36
Herbie Onge52379a2019-03-15 18:00:19 -070037 // Resolver is the registry used for type lookups when unmarshaling extensions
38 // and processing Any. If Resolver is not set, unmarshaling will default to
39 // using protoregistry.GlobalTypes.
40 Resolver *protoregistry.Types
Herbie Ong822de2d2019-03-27 13:16:23 -070041
42 decoder *json.Decoder
Herbie Onge52379a2019-03-15 18:00:19 -070043}
Herbie Ongc96a79d2019-03-08 10:49:17 -080044
45// Unmarshal reads the given []byte and populates the given proto.Message using
46// options in UnmarshalOptions object. It will clear the message first before
47// setting the fields. If it returns an error, the given message may be
48// partially set.
49func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
50 mr := m.ProtoReflect()
51 // TODO: Determine if we would like to have an option for merging or only
52 // have merging behavior. We should at least be consistent with textproto
53 // marshaling.
54 resetMessage(mr)
55
Herbie Ong822de2d2019-03-27 13:16:23 -070056 if o.Resolver == nil {
57 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070058 }
Herbie Ong822de2d2019-03-27 13:16:23 -070059 o.decoder = json.NewDecoder(b)
Herbie Onge52379a2019-03-15 18:00:19 -070060
Herbie Ongc96a79d2019-03-08 10:49:17 -080061 var nerr errors.NonFatal
Herbie Ong8ac9dd22019-03-27 12:20:50 -070062 if err := o.unmarshalMessage(mr, false); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -080063 return err
64 }
65
66 // Check for EOF.
Herbie Ong822de2d2019-03-27 13:16:23 -070067 val, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080068 if err != nil {
69 return err
70 }
71 if val.Type() != json.EOF {
72 return unexpectedJSONError{val}
73 }
Damien Neil4686e232019-04-05 13:31:40 -070074
75 if !o.AllowPartial {
76 nerr.Merge(proto.IsInitialized(m))
77 }
Herbie Ongc96a79d2019-03-08 10:49:17 -080078 return nerr.E
79}
80
81// resetMessage clears all fields of given protoreflect.Message.
82func resetMessage(m pref.Message) {
83 knownFields := m.KnownFields()
84 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
85 knownFields.Clear(num)
86 return true
87 })
88 unknownFields := m.UnknownFields()
89 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
90 unknownFields.Set(num, nil)
91 return true
92 })
93 extTypes := knownFields.ExtensionTypes()
94 extTypes.Range(func(xt pref.ExtensionType) bool {
95 extTypes.Remove(xt)
96 return true
97 })
98}
99
100// unexpectedJSONError is an error that contains the unexpected json.Value. This
Herbie Ong822de2d2019-03-27 13:16:23 -0700101// is returned by methods to provide callers the read json.Value that it did not
102// expect.
Herbie Ongc96a79d2019-03-08 10:49:17 -0800103// TODO: Consider moving this to internal/encoding/json for consistency with
104// errors that package returns.
105type unexpectedJSONError struct {
106 value json.Value
107}
108
109func (e unexpectedJSONError) Error() string {
110 return newError("unexpected value %s", e.value).Error()
111}
112
113// newError returns an error object. If one of the values passed in is of
114// json.Value type, it produces an error with position info.
115func newError(f string, x ...interface{}) error {
116 var hasValue bool
117 var line, column int
118 for i := 0; i < len(x); i++ {
119 if val, ok := x[i].(json.Value); ok {
120 line, column = val.Position()
121 hasValue = true
122 break
123 }
124 }
125 e := errors.New(f, x...)
126 if hasValue {
127 return errors.New("(line %d:%d): %v", line, column, e)
128 }
129 return e
130}
131
Herbie Ongc96a79d2019-03-08 10:49:17 -0800132// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700133func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800134 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800135
Herbie Onge63c4c42019-03-22 22:20:22 -0700136 if isCustomType(m.Type().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700137 return o.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700138 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800139
Herbie Ong822de2d2019-03-27 13:16:23 -0700140 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800141 if !nerr.Merge(err) {
142 return err
143 }
144 if jval.Type() != json.StartObject {
145 return unexpectedJSONError{jval}
146 }
147
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700148 if err := o.unmarshalFields(m, skipTypeURL); !nerr.Merge(err) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700149 return err
150 }
151
152 return nerr.E
153}
154
155// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700156func (o UnmarshalOptions) unmarshalFields(m pref.Message, skipTypeURL bool) error {
Herbie Onge63c4c42019-03-22 22:20:22 -0700157 var nerr errors.NonFatal
Herbie Onge63c4c42019-03-22 22:20:22 -0700158 var seenNums set.Ints
Herbie Ong8a1d4602019-04-02 20:19:36 -0700159 var seenOneofs set.Ints
Herbie Onge63c4c42019-03-22 22:20:22 -0700160
161 msgType := m.Type()
162 knownFields := m.KnownFields()
163 fieldDescs := msgType.Fields()
164 xtTypes := knownFields.ExtensionTypes()
165
Herbie Ongc96a79d2019-03-08 10:49:17 -0800166Loop:
167 for {
168 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700169 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800170 if !nerr.Merge(err) {
171 return err
172 }
173 switch jval.Type() {
174 default:
175 return unexpectedJSONError{jval}
176 case json.EndObject:
177 break Loop
178 case json.Name:
179 // Continue below.
180 }
181
182 name, err := jval.Name()
183 if !nerr.Merge(err) {
184 return err
185 }
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700186 // Unmarshaling a non-custom embedded message in Any will contain the
187 // JSON field "@type" which should be skipped because it is not a field
188 // of the embedded message, but simply an artifact of the Any format.
189 if skipTypeURL && name == "@type" {
190 o.decoder.Read()
191 continue
192 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800193
Herbie Onge52379a2019-03-15 18:00:19 -0700194 // Get the FieldDescriptor.
195 var fd pref.FieldDescriptor
196 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
197 // Only extension names are in [name] format.
198 xtName := pref.FullName(name[1 : len(name)-1])
199 xt := xtTypes.ByName(xtName)
200 if xt == nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700201 xt, err = o.findExtension(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700202 if err != nil && err != protoregistry.NotFound {
203 return errors.New("unable to resolve [%v]: %v", xtName, err)
204 }
205 if xt != nil {
206 xtTypes.Register(xt)
207 }
208 }
209 fd = xt
210 } else {
211 // The name can either be the JSON name or the proto field name.
212 fd = fieldDescs.ByJSONName(name)
213 if fd == nil {
214 fd = fieldDescs.ByName(pref.Name(name))
215 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800216 }
217
218 if fd == nil {
219 // Field is unknown.
220 // TODO: Provide option to ignore unknown message fields.
221 return newError("%v contains unknown field %s", msgType.FullName(), jval)
222 }
223
224 // Do not allow duplicate fields.
225 num := uint64(fd.Number())
226 if seenNums.Has(num) {
227 return newError("%v contains repeated field %s", msgType.FullName(), jval)
228 }
229 seenNums.Set(num)
230
Herbie Onge63c4c42019-03-22 22:20:22 -0700231 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700232 // google.protobuf.Value or google.protobuf.NullValue.
233 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700234 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800235 continue
236 }
237
238 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
239 // Map or list fields have cardinality of repeated.
Herbie Ong822de2d2019-03-27 13:16:23 -0700240 if err := o.unmarshalRepeated(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800241 return errors.New("%v|%q: %v", fd.FullName(), name, err)
242 }
243 } else {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700244 // If field is a oneof, check if it has already been set.
Joe Tsaid24bc722019-04-15 23:39:09 -0700245 if od := fd.Oneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700246 idx := uint64(od.Index())
247 if seenOneofs.Has(idx) {
248 return errors.New("%v: oneof is already set", od.FullName())
249 }
250 seenOneofs.Set(idx)
251 }
252
Herbie Ongc96a79d2019-03-08 10:49:17 -0800253 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700254 if err := o.unmarshalSingular(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800255 return errors.New("%v|%q: %v", fd.FullName(), name, err)
256 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800257 }
258 }
259
260 return nerr.E
261}
262
Herbie Onge52379a2019-03-15 18:00:19 -0700263// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700264func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
265 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700266 if err == nil {
267 return xt, nil
268 }
269
270 // Check if this is a MessageSet extension field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700271 xt, err = o.Resolver.FindExtensionByName(xtName + ".message_set_extension")
Herbie Onge52379a2019-03-15 18:00:19 -0700272 if err == nil && isMessageSetExtension(xt) {
273 return xt, nil
274 }
275 return nil, protoregistry.NotFound
276}
277
Herbie Ong300b9fe2019-03-29 15:42:20 -0700278func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700279 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700280 return md != nil && md.FullName() == "google.protobuf.Value"
281}
282
283func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700284 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700285 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
286}
287
Herbie Ongc96a79d2019-03-08 10:49:17 -0800288// unmarshalSingular unmarshals to the non-repeated field specified by the given
289// FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700290func (o UnmarshalOptions) unmarshalSingular(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800291 var val pref.Value
292 var err error
293 num := fd.Number()
294
295 switch fd.Kind() {
296 case pref.MessageKind, pref.GroupKind:
297 m := knownFields.NewMessage(num)
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700298 err = o.unmarshalMessage(m, false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800299 val = pref.ValueOf(m)
300 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700301 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800302 }
303
304 var nerr errors.NonFatal
305 if !nerr.Merge(err) {
306 return err
307 }
308 knownFields.Set(num, val)
309 return nerr.E
310}
311
312// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
313// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700314func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800315 const b32 int = 32
316 const b64 int = 64
317
318 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700319 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800320 if !nerr.Merge(err) {
321 return pref.Value{}, err
322 }
323
324 kind := fd.Kind()
325 switch kind {
326 case pref.BoolKind:
327 return unmarshalBool(jval)
328
329 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
330 return unmarshalInt(jval, b32)
331
332 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
333 return unmarshalInt(jval, b64)
334
335 case pref.Uint32Kind, pref.Fixed32Kind:
336 return unmarshalUint(jval, b32)
337
338 case pref.Uint64Kind, pref.Fixed64Kind:
339 return unmarshalUint(jval, b64)
340
341 case pref.FloatKind:
342 return unmarshalFloat(jval, b32)
343
344 case pref.DoubleKind:
345 return unmarshalFloat(jval, b64)
346
347 case pref.StringKind:
348 pval, err := unmarshalString(jval)
349 if !nerr.Merge(err) {
350 return pval, err
351 }
352 return pval, nerr.E
353
354 case pref.BytesKind:
355 return unmarshalBytes(jval)
356
357 case pref.EnumKind:
358 return unmarshalEnum(jval, fd)
359 }
360
361 panic(fmt.Sprintf("invalid scalar kind %v", kind))
362}
363
364func unmarshalBool(jval json.Value) (pref.Value, error) {
365 if jval.Type() != json.Bool {
366 return pref.Value{}, unexpectedJSONError{jval}
367 }
368 b, err := jval.Bool()
369 return pref.ValueOf(b), err
370}
371
372func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
373 switch jval.Type() {
374 case json.Number:
375 return getInt(jval, bitSize)
376
377 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700378 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700379 s := strings.TrimSpace(jval.String())
380 if len(s) != len(jval.String()) {
381 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
382 }
383 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800384 var nerr errors.NonFatal
385 jval, err := dec.Read()
386 if !nerr.Merge(err) {
387 return pref.Value{}, err
388 }
389 return getInt(jval, bitSize)
390 }
391 return pref.Value{}, unexpectedJSONError{jval}
392}
393
394func getInt(jval json.Value, bitSize int) (pref.Value, error) {
395 n, err := jval.Int(bitSize)
396 if err != nil {
397 return pref.Value{}, err
398 }
399 if bitSize == 32 {
400 return pref.ValueOf(int32(n)), nil
401 }
402 return pref.ValueOf(n), nil
403}
404
405func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
406 switch jval.Type() {
407 case json.Number:
408 return getUint(jval, bitSize)
409
410 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700411 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700412 s := strings.TrimSpace(jval.String())
413 if len(s) != len(jval.String()) {
414 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
415 }
416 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800417 var nerr errors.NonFatal
418 jval, err := dec.Read()
419 if !nerr.Merge(err) {
420 return pref.Value{}, err
421 }
422 return getUint(jval, bitSize)
423 }
424 return pref.Value{}, unexpectedJSONError{jval}
425}
426
427func getUint(jval json.Value, bitSize int) (pref.Value, error) {
428 n, err := jval.Uint(bitSize)
429 if err != nil {
430 return pref.Value{}, err
431 }
432 if bitSize == 32 {
433 return pref.ValueOf(uint32(n)), nil
434 }
435 return pref.ValueOf(n), nil
436}
437
438func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
439 switch jval.Type() {
440 case json.Number:
441 return getFloat(jval, bitSize)
442
443 case json.String:
444 s := jval.String()
445 switch s {
446 case "NaN":
447 if bitSize == 32 {
448 return pref.ValueOf(float32(math.NaN())), nil
449 }
450 return pref.ValueOf(math.NaN()), nil
451 case "Infinity":
452 if bitSize == 32 {
453 return pref.ValueOf(float32(math.Inf(+1))), nil
454 }
455 return pref.ValueOf(math.Inf(+1)), nil
456 case "-Infinity":
457 if bitSize == 32 {
458 return pref.ValueOf(float32(math.Inf(-1))), nil
459 }
460 return pref.ValueOf(math.Inf(-1)), nil
461 }
Herbie Onge52379a2019-03-15 18:00:19 -0700462 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700463 if len(s) != len(strings.TrimSpace(s)) {
464 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
465 }
Herbie Onge52379a2019-03-15 18:00:19 -0700466 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800467 var nerr errors.NonFatal
468 jval, err := dec.Read()
469 if !nerr.Merge(err) {
470 return pref.Value{}, err
471 }
472 return getFloat(jval, bitSize)
473 }
474 return pref.Value{}, unexpectedJSONError{jval}
475}
476
477func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
478 n, err := jval.Float(bitSize)
479 if err != nil {
480 return pref.Value{}, err
481 }
482 if bitSize == 32 {
483 return pref.ValueOf(float32(n)), nil
484 }
485 return pref.ValueOf(n), nil
486}
487
488func unmarshalString(jval json.Value) (pref.Value, error) {
489 if jval.Type() != json.String {
490 return pref.Value{}, unexpectedJSONError{jval}
491 }
492 return pref.ValueOf(jval.String()), nil
493}
494
495func unmarshalBytes(jval json.Value) (pref.Value, error) {
496 if jval.Type() != json.String {
497 return pref.Value{}, unexpectedJSONError{jval}
498 }
499
500 s := jval.String()
501 enc := base64.StdEncoding
502 if strings.ContainsAny(s, "-_") {
503 enc = base64.URLEncoding
504 }
505 if len(s)%4 != 0 {
506 enc = enc.WithPadding(base64.NoPadding)
507 }
508 b, err := enc.DecodeString(s)
509 if err != nil {
510 return pref.Value{}, err
511 }
512 return pref.ValueOf(b), nil
513}
514
515func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
516 switch jval.Type() {
517 case json.String:
518 // Lookup EnumNumber based on name.
519 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700520 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800521 return pref.ValueOf(enumVal.Number()), nil
522 }
523 return pref.Value{}, newError("invalid enum value %q", jval)
524
525 case json.Number:
526 n, err := jval.Int(32)
527 if err != nil {
528 return pref.Value{}, err
529 }
530 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700531
532 case json.Null:
533 // This is only valid for google.protobuf.NullValue.
534 if isNullValue(fd) {
535 return pref.ValueOf(pref.EnumNumber(0)), nil
536 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800537 }
538
539 return pref.Value{}, unexpectedJSONError{jval}
540}
541
542// unmarshalRepeated unmarshals into a repeated field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700543func (o UnmarshalOptions) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800544 var nerr errors.NonFatal
545 num := fd.Number()
546 val := knownFields.Get(num)
547 if !fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700548 if err := o.unmarshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800549 return err
550 }
551 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700552 if err := o.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800553 return err
554 }
555 }
556 return nerr.E
557}
558
559// unmarshalList unmarshals into given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700560func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800561 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700562 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800563 if !nerr.Merge(err) {
564 return err
565 }
566 if jval.Type() != json.StartArray {
567 return unexpectedJSONError{jval}
568 }
569
570 switch fd.Kind() {
571 case pref.MessageKind, pref.GroupKind:
572 for {
573 m := list.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700574 err := o.unmarshalMessage(m, false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800575 if !nerr.Merge(err) {
576 if e, ok := err.(unexpectedJSONError); ok {
577 if e.value.Type() == json.EndArray {
578 // Done with list.
579 return nerr.E
580 }
581 }
582 return err
583 }
584 list.Append(pref.ValueOf(m))
585 }
586 default:
587 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700588 val, err := o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800589 if !nerr.Merge(err) {
590 if e, ok := err.(unexpectedJSONError); ok {
591 if e.value.Type() == json.EndArray {
592 // Done with list.
593 return nerr.E
594 }
595 }
596 return err
597 }
598 list.Append(val)
599 }
600 }
601 return nerr.E
602}
603
604// unmarshalMap unmarshals into given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700605func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800606 var nerr errors.NonFatal
607
Herbie Ong822de2d2019-03-27 13:16:23 -0700608 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800609 if !nerr.Merge(err) {
610 return err
611 }
612 if jval.Type() != json.StartObject {
613 return unexpectedJSONError{jval}
614 }
615
Joe Tsaid24bc722019-04-15 23:39:09 -0700616 fields := fd.Message().Fields()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800617 keyDesc := fields.ByNumber(1)
618 valDesc := fields.ByNumber(2)
619
620 // Determine ahead whether map entry is a scalar type or a message type in
621 // order to call the appropriate unmarshalMapValue func inside the for loop
622 // below.
623 unmarshalMapValue := func() (pref.Value, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700624 return o.unmarshalScalar(valDesc)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800625 }
626 switch valDesc.Kind() {
627 case pref.MessageKind, pref.GroupKind:
628 unmarshalMapValue = func() (pref.Value, error) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700629 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800630 m := mmap.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700631 if err := o.unmarshalMessage(m, false); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800632 return pref.Value{}, err
633 }
Herbie Onge63c4c42019-03-22 22:20:22 -0700634 return pref.ValueOf(m), nerr.E
Herbie Ongc96a79d2019-03-08 10:49:17 -0800635 }
636 }
637
638Loop:
639 for {
640 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700641 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800642 if !nerr.Merge(err) {
643 return err
644 }
645 switch jval.Type() {
646 default:
647 return unexpectedJSONError{jval}
648 case json.EndObject:
649 break Loop
650 case json.Name:
651 // Continue.
652 }
653
654 name, err := jval.Name()
655 if !nerr.Merge(err) {
656 return err
657 }
658
659 // Unmarshal field name.
660 pkey, err := unmarshalMapKey(name, keyDesc)
661 if !nerr.Merge(err) {
662 return err
663 }
664
665 // Check for duplicate field name.
666 if mmap.Has(pkey) {
667 return newError("duplicate map key %q", jval)
668 }
669
670 // Read and unmarshal field value.
671 pval, err := unmarshalMapValue()
672 if !nerr.Merge(err) {
673 return err
674 }
675
676 mmap.Set(pkey, pval)
677 }
678
679 return nerr.E
680}
681
682// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
683// integral or string type.
684func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
685 const b32 = 32
686 const b64 = 64
687 const base10 = 10
688
689 kind := fd.Kind()
690 switch kind {
691 case pref.StringKind:
692 return pref.ValueOf(name).MapKey(), nil
693
694 case pref.BoolKind:
695 switch name {
696 case "true":
697 return pref.ValueOf(true).MapKey(), nil
698 case "false":
699 return pref.ValueOf(false).MapKey(), nil
700 }
701 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
702
703 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
704 n, err := strconv.ParseInt(name, base10, b32)
705 if err != nil {
706 return pref.MapKey{}, err
707 }
708 return pref.ValueOf(int32(n)).MapKey(), nil
709
710 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
711 n, err := strconv.ParseInt(name, base10, b64)
712 if err != nil {
713 return pref.MapKey{}, err
714 }
715 return pref.ValueOf(int64(n)).MapKey(), nil
716
717 case pref.Uint32Kind, pref.Fixed32Kind:
718 n, err := strconv.ParseUint(name, base10, b32)
719 if err != nil {
720 return pref.MapKey{}, err
721 }
722 return pref.ValueOf(uint32(n)).MapKey(), nil
723
724 case pref.Uint64Kind, pref.Fixed64Kind:
725 n, err := strconv.ParseUint(name, base10, b64)
726 if err != nil {
727 return pref.MapKey{}, err
728 }
729 return pref.ValueOf(uint64(n)).MapKey(), nil
730 }
731
732 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
733}