@@ -436,7 +436,7 @@ func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
436
436
if err := dec .Decode (& inputValue ); err != nil {
437
437
return err
438
438
}
439
- return unmarshalValue (reflect .ValueOf (pb ).Elem (), inputValue )
439
+ return unmarshalValue (reflect .ValueOf (pb ).Elem (), inputValue , nil )
440
440
}
441
441
442
442
// Unmarshal unmarshals a JSON object stream into a protocol
@@ -455,13 +455,14 @@ func UnmarshalString(str string, pb proto.Message) error {
455
455
}
456
456
457
457
// unmarshalValue converts/copies a value into the target.
458
- func unmarshalValue (target reflect.Value , inputValue json.RawMessage ) error {
458
+ // prop may be nil.
459
+ func unmarshalValue (target reflect.Value , inputValue json.RawMessage , prop * proto.Properties ) error {
459
460
targetType := target .Type ()
460
461
461
462
// Allocate memory for pointer fields.
462
463
if targetType .Kind () == reflect .Ptr {
463
464
target .Set (reflect .New (targetType .Elem ()))
464
- return unmarshalValue (target .Elem (), inputValue )
465
+ return unmarshalValue (target .Elem (), inputValue , prop )
465
466
}
466
467
467
468
// Handle well-known types.
@@ -476,7 +477,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
476
477
// as the wrapped primitive type, except that null is allowed."
477
478
// encoding/json will turn JSON `null` into Go `nil`,
478
479
// so we don't have to do any extra work.
479
- return unmarshalValue (target .Field (0 ), inputValue )
480
+ return unmarshalValue (target .Field (0 ), inputValue , prop )
480
481
case "Duration" :
481
482
unq , err := strconv .Unquote (string (inputValue ))
482
483
if err != nil {
@@ -510,6 +511,27 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
510
511
}
511
512
}
512
513
514
+ // Handle enums, which have an underlying type of int32,
515
+ // and may appear as strings.
516
+ // The case of an enum appearing as a number is handled
517
+ // at the bottom of this function.
518
+ if inputValue [0 ] == '"' && prop != nil && prop .Enum != "" {
519
+ vmap := proto .EnumValueMap (prop .Enum )
520
+ // Don't need to do unquoting; valid enum names
521
+ // are from a limited character set.
522
+ s := inputValue [1 : len (inputValue )- 1 ]
523
+ n , ok := vmap [string (s )]
524
+ if ! ok {
525
+ return fmt .Errorf ("unknown value %q for enum %s" , s , prop .Enum )
526
+ }
527
+ if target .Kind () == reflect .Ptr { // proto2
528
+ target .Set (reflect .New (targetType .Elem ()))
529
+ target = target .Elem ()
530
+ }
531
+ target .SetInt (int64 (n ))
532
+ return nil
533
+ }
534
+
513
535
// Handle nested messages.
514
536
if targetType .Kind () == reflect .Struct {
515
537
var jsonFields map [string ]json.RawMessage
@@ -551,30 +573,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
551
573
continue
552
574
}
553
575
554
- // Handle enums, which have an underlying type of int32,
555
- // and may appear as strings. We do this while handling
556
- // the struct so we have access to the enum info.
557
- // The case of an enum appearing as a number is handled
558
- // by the recursive call to unmarshalValue.
559
- if enum := sprops .Prop [i ].Enum ; valueForField [0 ] == '"' && enum != "" {
560
- vmap := proto .EnumValueMap (enum )
561
- // Don't need to do unquoting; valid enum names
562
- // are from a limited character set.
563
- s := valueForField [1 : len (valueForField )- 1 ]
564
- n , ok := vmap [string (s )]
565
- if ! ok {
566
- return fmt .Errorf ("unknown value %q for enum %s" , s , enum )
567
- }
568
- f := target .Field (i )
569
- if f .Kind () == reflect .Ptr { // proto2
570
- f .Set (reflect .New (f .Type ().Elem ()))
571
- f = f .Elem ()
572
- }
573
- f .SetInt (int64 (n ))
574
- continue
575
- }
576
-
577
- if err := unmarshalValue (target .Field (i ), valueForField ); err != nil {
576
+ if err := unmarshalValue (target .Field (i ), valueForField , sprops .Prop [i ]); err != nil {
578
577
return err
579
578
}
580
579
}
@@ -587,7 +586,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
587
586
}
588
587
nv := reflect .New (oop .Type .Elem ())
589
588
target .Field (oop .Field ).Set (nv )
590
- if err := unmarshalValue (nv .Elem ().Field (0 ), raw ); err != nil {
589
+ if err := unmarshalValue (nv .Elem ().Field (0 ), raw , oop . Prop ); err != nil {
591
590
return err
592
591
}
593
592
}
@@ -613,7 +612,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
613
612
len := len (slc )
614
613
target .Set (reflect .MakeSlice (targetType , len , len ))
615
614
for i := 0 ; i < len ; i ++ {
616
- if err := unmarshalValue (target .Index (i ), slc [i ]); err != nil {
615
+ if err := unmarshalValue (target .Index (i ), slc [i ], prop ); err != nil {
617
616
return err
618
617
}
619
618
}
@@ -627,6 +626,13 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
627
626
return err
628
627
}
629
628
target .Set (reflect .MakeMap (targetType ))
629
+ var keyprop , valprop * proto.Properties
630
+ if prop != nil {
631
+ // These could still be nil if the protobuf metadata is broken somehow.
632
+ // TODO: This won't work because the fields are unexported.
633
+ // We should probably just reparse them.
634
+ //keyprop, valprop = prop.mkeyprop, prop.mvalprop
635
+ }
630
636
for ks , raw := range mp {
631
637
// Unmarshal map key. The core json library already decoded the key into a
632
638
// string, so we handle that specially. Other types were quoted post-serialization.
@@ -635,14 +641,14 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error {
635
641
k = reflect .ValueOf (ks )
636
642
} else {
637
643
k = reflect .New (targetType .Key ()).Elem ()
638
- if err := unmarshalValue (k , json .RawMessage (ks )); err != nil {
644
+ if err := unmarshalValue (k , json .RawMessage (ks ), keyprop ); err != nil {
639
645
return err
640
646
}
641
647
}
642
648
643
649
// Unmarshal map value.
644
650
v := reflect .New (targetType .Elem ()).Elem ()
645
- if err := unmarshalValue (v , raw ); err != nil {
651
+ if err := unmarshalValue (v , raw , valprop ); err != nil {
646
652
return err
647
653
}
648
654
target .SetMapIndex (k , v )
0 commit comments