@@ -6,6 +6,7 @@ package json
6
6
7
7
import (
8
8
"bytes"
9
+ "encoding"
9
10
"encoding/base32"
10
11
"encoding/base64"
11
12
"encoding/hex"
@@ -724,6 +725,8 @@ func makeMapArshaler(t reflect.Type) *arshaler {
724
725
keyFncs = lookupArshaler (t .Key ())
725
726
valFncs = lookupArshaler (t .Elem ())
726
727
}
728
+ nillableLegacyKey := t .Key ().Kind () == reflect .Pointer &&
729
+ implementsAny (t .Key (), textMarshalerType , textAppenderType )
727
730
fncs .marshal = func (enc * jsontext.Encoder , va addressableValue , mo * jsonopts.Struct ) error {
728
731
// Check for cycles.
729
732
xe := export .Encoder (enc )
@@ -795,10 +798,16 @@ func makeMapArshaler(t reflect.Type) *arshaler {
795
798
k .SetIterKey (iter )
796
799
err := marshalKey (enc , k , mo )
797
800
if err != nil {
798
- if serr , ok := err .(* jsontext.SyntacticError ); ok && serr .Err == jsontext .ErrNonStringName {
799
- err = newMarshalErrorBefore (enc , k .Type (), err )
801
+ if mo .Flags .Get (jsonflags .CallMethodsWithLegacySemantics ) &&
802
+ errors .Is (err , jsontext .ErrNonStringName ) && nillableLegacyKey && k .IsNil () {
803
+ err = enc .WriteToken (jsontext .String ("" ))
804
+ }
805
+ if err != nil {
806
+ if serr , ok := err .(* jsontext.SyntacticError ); ok && serr .Err == jsontext .ErrNonStringName {
807
+ err = newMarshalErrorBefore (enc , k .Type (), err )
808
+ }
809
+ return err
800
810
}
801
- return err
802
811
}
803
812
v .SetIterValue (iter )
804
813
if err := marshalVal (enc , v , mo ); err != nil {
@@ -835,16 +844,22 @@ func makeMapArshaler(t reflect.Type) *arshaler {
835
844
vals := reflect .MakeSlice (reflect .SliceOf (t .Elem ()), n , n )
836
845
for i , iter := 0 , va .Value .MapRange (); i < n && iter .Next (); i ++ {
837
846
// Marshal the member name.
838
- k := addressableValue {keys .Index (i )} // indexed slice element is always addressable
847
+ k := addressableValue {keys .Index (i ), false } // indexed slice element is always addressable
839
848
k .SetIterKey (iter )
840
- v := addressableValue {vals .Index (i )} // indexed slice element is always addressable
849
+ v := addressableValue {vals .Index (i ), false } // indexed slice element is always addressable
841
850
v .SetIterValue (iter )
842
851
err := marshalKey (enc , k , mo )
843
852
if err != nil {
844
- if serr , ok := err .(* jsontext.SyntacticError ); ok && serr .Err == jsontext .ErrNonStringName {
845
- err = newMarshalErrorBefore (enc , k .Type (), err )
853
+ if mo .Flags .Get (jsonflags .CallMethodsWithLegacySemantics ) &&
854
+ errors .Is (err , jsontext .ErrNonStringName ) && nillableLegacyKey && k .IsNil () {
855
+ err = enc .WriteToken (jsontext .String ("" ))
856
+ }
857
+ if err != nil {
858
+ if serr , ok := err .(* jsontext.SyntacticError ); ok && serr .Err == jsontext .ErrNonStringName {
859
+ err = newMarshalErrorBefore (enc , k .Type (), err )
860
+ }
861
+ return err
846
862
}
847
- return err
848
863
}
849
864
name := xe .UnwriteOnlyObjectMemberName ()
850
865
members [i ] = member {name , k , v }
@@ -1027,7 +1042,7 @@ func makeStructArshaler(t reflect.Type) *arshaler {
1027
1042
xe .Tokens .Last .DisableNamespace () // we manually ensure unique names below
1028
1043
for i := range fields .flattened {
1029
1044
f := & fields .flattened [i ]
1030
- v := addressableValue {va .Field (f .index [0 ])} // addressable if struct value is addressable
1045
+ v := addressableValue {va .Field (f .index [0 ]), va . forcedAddr } // addressable if struct value is addressable
1031
1046
if len (f .index ) > 1 {
1032
1047
v = v .fieldByIndex (f .index [1 :], false )
1033
1048
if ! v .IsValid () {
@@ -1256,7 +1271,7 @@ func makeStructArshaler(t reflect.Type) *arshaler {
1256
1271
uo .FormatDepth = xd .Tokens .Depth ()
1257
1272
uo .Format = f .format
1258
1273
}
1259
- v := addressableValue {va .Field (f .index [0 ])} // addressable if struct value is addressable
1274
+ v := addressableValue {va .Field (f .index [0 ]), va . forcedAddr } // addressable if struct value is addressable
1260
1275
if len (f .index ) > 1 {
1261
1276
v = v .fieldByIndex (f .index [1 :], true )
1262
1277
if ! v .IsValid () {
@@ -1286,7 +1301,7 @@ func (va addressableValue) fieldByIndex(index []int, mayAlloc bool) addressableV
1286
1301
if ! va .IsValid () {
1287
1302
return va
1288
1303
}
1289
- va = addressableValue {va .Field (i )} // addressable if struct value is addressable
1304
+ va = addressableValue {va .Field (i ), va . forcedAddr } // addressable if struct value is addressable
1290
1305
}
1291
1306
return va
1292
1307
}
@@ -1299,7 +1314,7 @@ func (va addressableValue) indirect(mayAlloc bool) addressableValue {
1299
1314
}
1300
1315
va .Set (reflect .New (va .Type ().Elem ()))
1301
1316
}
1302
- va = addressableValue {va .Elem ()} // dereferenced pointer is always addressable
1317
+ va = addressableValue {va .Elem (), false } // dereferenced pointer is always addressable
1303
1318
}
1304
1319
return va
1305
1320
}
@@ -1402,7 +1417,7 @@ func makeSliceArshaler(t reflect.Type) *arshaler {
1402
1417
marshal , _ = mo .Marshalers .(* Marshalers ).lookup (marshal , t .Elem ())
1403
1418
}
1404
1419
for i := range n {
1405
- v := addressableValue {va .Index (i )} // indexed slice element is always addressable
1420
+ v := addressableValue {va .Index (i ), false } // indexed slice element is always addressable
1406
1421
if err := marshal (enc , v , mo ); err != nil {
1407
1422
return err
1408
1423
}
@@ -1452,7 +1467,7 @@ func makeSliceArshaler(t reflect.Type) *arshaler {
1452
1467
va .SetLen (cap )
1453
1468
mustZero = false // reflect.Value.Grow ensures new capacity is zero-initialized
1454
1469
}
1455
- v := addressableValue {va .Index (i )} // indexed slice element is always addressable
1470
+ v := addressableValue {va .Index (i ), false } // indexed slice element is always addressable
1456
1471
i ++
1457
1472
if mustZero && ! uo .Flags .Get (jsonflags .MergeWithLegacySemantics ) {
1458
1473
v .SetZero ()
@@ -1504,7 +1519,7 @@ func makeArrayArshaler(t reflect.Type) *arshaler {
1504
1519
marshal , _ = mo .Marshalers .(* Marshalers ).lookup (marshal , t .Elem ())
1505
1520
}
1506
1521
for i := range n {
1507
- v := addressableValue {va .Index (i )} // indexed array element is addressable if array is addressable
1522
+ v := addressableValue {va .Index (i ), va . forcedAddr } // indexed array element is addressable if array is addressable
1508
1523
if err := marshal (enc , v , mo ); err != nil {
1509
1524
return err
1510
1525
}
@@ -1545,7 +1560,7 @@ func makeArrayArshaler(t reflect.Type) *arshaler {
1545
1560
err = errArrayOverflow
1546
1561
continue
1547
1562
}
1548
- v := addressableValue {va .Index (i )} // indexed array element is addressable if array is addressable
1563
+ v := addressableValue {va .Index (i ), va . forcedAddr } // indexed array element is addressable if array is addressable
1549
1564
if ! uo .Flags .Get (jsonflags .MergeWithLegacySemantics ) {
1550
1565
v .SetZero ()
1551
1566
}
@@ -1599,7 +1614,7 @@ func makePointerArshaler(t reflect.Type) *arshaler {
1599
1614
if mo .Marshalers != nil {
1600
1615
marshal , _ = mo .Marshalers .(* Marshalers ).lookup (marshal , t .Elem ())
1601
1616
}
1602
- v := addressableValue {va .Elem ()} // dereferenced pointer is always addressable
1617
+ v := addressableValue {va .Elem (), false } // dereferenced pointer is always addressable
1603
1618
return marshal (enc , v , mo )
1604
1619
}
1605
1620
fncs .unmarshal = func (dec * jsontext.Decoder , va addressableValue , uo * jsonopts.Struct ) error {
@@ -1619,7 +1634,7 @@ func makePointerArshaler(t reflect.Type) *arshaler {
1619
1634
if va .IsNil () {
1620
1635
va .Set (reflect .New (t .Elem ()))
1621
1636
}
1622
- v := addressableValue {va .Elem ()} // dereferenced pointer is always addressable
1637
+ v := addressableValue {va .Elem (), false } // dereferenced pointer is always addressable
1623
1638
if err := unmarshal (dec , v , uo ); err != nil {
1624
1639
return err
1625
1640
}
@@ -1648,13 +1663,38 @@ func makeInterfaceArshaler(t reflect.Type) *arshaler {
1648
1663
// store them back into the interface afterwards.
1649
1664
1650
1665
var fncs arshaler
1666
+ var whichMarshaler reflect.Type
1667
+ for _ , iface := range allMarshalerTypes {
1668
+ if t .Implements (iface ) {
1669
+ whichMarshaler = t
1670
+ break
1671
+ }
1672
+ }
1651
1673
fncs .marshal = func (enc * jsontext.Encoder , va addressableValue , mo * jsonopts.Struct ) error {
1652
1674
xe := export .Encoder (enc )
1653
1675
if mo .Format != "" && mo .FormatDepth == xe .Tokens .Depth () {
1654
1676
return newInvalidFormatError (enc , t , mo .Format )
1655
1677
}
1656
1678
if va .IsNil () {
1657
1679
return enc .WriteToken (jsontext .Null )
1680
+ } else if mo .Flags .Get (jsonflags .CallMethodsWithLegacySemantics ) && whichMarshaler != nil {
1681
+ // The marshaler for a pointer never calls the method on a nil receiver.
1682
+ // Wrap the nil pointer within a struct type so that marshal
1683
+ // instead appears on a value receiver and may be called.
1684
+ if va .Elem ().Kind () == reflect .Pointer && va .Elem ().IsNil () {
1685
+ v2 := newAddressableValue (whichMarshaler )
1686
+ switch whichMarshaler {
1687
+ case jsonMarshalerV2Type :
1688
+ v2 .Set (reflect .ValueOf (struct { MarshalerV2 }{va .Elem ().Interface ().(MarshalerV2 )}))
1689
+ case jsonMarshalerV1Type :
1690
+ v2 .Set (reflect .ValueOf (struct { MarshalerV1 }{va .Elem ().Interface ().(MarshalerV1 )}))
1691
+ case textAppenderType :
1692
+ v2 .Set (reflect .ValueOf (struct { encodingTextAppender }{va .Elem ().Interface ().(encodingTextAppender )}))
1693
+ case textMarshalerType :
1694
+ v2 .Set (reflect .ValueOf (struct { encoding.TextMarshaler }{va .Elem ().Interface ().(encoding.TextMarshaler )}))
1695
+ }
1696
+ va = v2
1697
+ }
1658
1698
}
1659
1699
v := newAddressableValue (va .Elem ().Type ())
1660
1700
v .Set (va .Elem ())
@@ -1731,7 +1771,7 @@ func makeInterfaceArshaler(t reflect.Type) *arshaler {
1731
1771
v = newAddressableValue (stringType )
1732
1772
case '0' :
1733
1773
if uo .Flags .Get (jsonflags .UnmarshalAnyWithRawNumber ) {
1734
- v = addressableValue {reflect .ValueOf (internal .NewRawNumber ()).Elem ()}
1774
+ v = addressableValue {reflect .ValueOf (internal .NewRawNumber ()).Elem (), true }
1735
1775
} else {
1736
1776
v = newAddressableValue (float64Type )
1737
1777
}
0 commit comments