@@ -11,6 +11,7 @@ import (
11
11
"fmt"
12
12
"image"
13
13
"math"
14
+ "math/big"
14
15
"net"
15
16
"reflect"
16
17
"strconv"
@@ -1524,40 +1525,148 @@ func TestInterfaceSet(t *testing.T) {
1524
1525
}
1525
1526
}
1526
1527
1528
+ type NullTest struct {
1529
+ Bool bool
1530
+ Int int
1531
+ Int8 int8
1532
+ Int16 int16
1533
+ Int32 int32
1534
+ Int64 int64
1535
+ Uint uint
1536
+ Uint8 uint8
1537
+ Uint16 uint16
1538
+ Uint32 uint32
1539
+ Uint64 uint64
1540
+ Float32 float32
1541
+ Float64 float64
1542
+ String string
1543
+ PBool * bool
1544
+ Map map [string ]string
1545
+ Slice []string
1546
+ Interface interface {}
1547
+
1548
+ PRaw * RawMessage
1549
+ PTime * time.Time
1550
+ PBigInt * big.Int
1551
+ PText * MustNotUnmarshalText
1552
+ PBuffer * bytes.Buffer // has methods, just not relevant ones
1553
+ PStruct * struct {}
1554
+
1555
+ Raw RawMessage
1556
+ Time time.Time
1557
+ BigInt big.Int
1558
+ Text MustNotUnmarshalText
1559
+ Buffer bytes.Buffer
1560
+ Struct struct {}
1561
+ }
1562
+
1563
+ type NullTestStrings struct {
1564
+ Bool bool `json:",string"`
1565
+ Int int `json:",string"`
1566
+ Int8 int8 `json:",string"`
1567
+ Int16 int16 `json:",string"`
1568
+ Int32 int32 `json:",string"`
1569
+ Int64 int64 `json:",string"`
1570
+ Uint uint `json:",string"`
1571
+ Uint8 uint8 `json:",string"`
1572
+ Uint16 uint16 `json:",string"`
1573
+ Uint32 uint32 `json:",string"`
1574
+ Uint64 uint64 `json:",string"`
1575
+ Float32 float32 `json:",string"`
1576
+ Float64 float64 `json:",string"`
1577
+ String string `json:",string"`
1578
+ PBool * bool `json:",string"`
1579
+ Map map [string ]string `json:",string"`
1580
+ Slice []string `json:",string"`
1581
+ Interface interface {} `json:",string"`
1582
+
1583
+ PRaw * RawMessage `json:",string"`
1584
+ PTime * time.Time `json:",string"`
1585
+ PBigInt * big.Int `json:",string"`
1586
+ PText * MustNotUnmarshalText `json:",string"`
1587
+ PBuffer * bytes.Buffer `json:",string"`
1588
+ PStruct * struct {} `json:",string"`
1589
+
1590
+ Raw RawMessage `json:",string"`
1591
+ Time time.Time `json:",string"`
1592
+ BigInt big.Int `json:",string"`
1593
+ Text MustNotUnmarshalText `json:",string"`
1594
+ Buffer bytes.Buffer `json:",string"`
1595
+ Struct struct {} `json:",string"`
1596
+ }
1597
+
1527
1598
// JSON null values should be ignored for primitives and string values instead of resulting in an error.
1528
1599
// Issue 2540
1529
1600
func TestUnmarshalNulls (t * testing.T ) {
1601
+ // Unmarshal docs:
1602
+ // The JSON null value unmarshals into an interface, map, pointer, or slice
1603
+ // by setting that Go value to nil. Because null is often used in JSON to mean
1604
+ // ``not present,'' unmarshaling a JSON null into any other Go type has no effect
1605
+ // on the value and produces no error.
1606
+
1530
1607
jsonData := []byte (`{
1531
- "Bool" : null,
1532
- "Int" : null,
1533
- "Int8" : null,
1534
- "Int16" : null,
1535
- "Int32" : null,
1536
- "Int64" : null,
1537
- "Uint" : null,
1538
- "Uint8" : null,
1539
- "Uint16" : null,
1540
- "Uint32" : null,
1541
- "Uint64" : null,
1542
- "Float32" : null,
1543
- "Float64" : null,
1544
- "String" : null}` )
1545
-
1546
- nulls := All {
1547
- Bool : true ,
1548
- Int : 2 ,
1549
- Int8 : 3 ,
1550
- Int16 : 4 ,
1551
- Int32 : 5 ,
1552
- Int64 : 6 ,
1553
- Uint : 7 ,
1554
- Uint8 : 8 ,
1555
- Uint16 : 9 ,
1556
- Uint32 : 10 ,
1557
- Uint64 : 11 ,
1558
- Float32 : 12.1 ,
1559
- Float64 : 13.1 ,
1560
- String : "14" }
1608
+ "Bool" : null,
1609
+ "Int" : null,
1610
+ "Int8" : null,
1611
+ "Int16" : null,
1612
+ "Int32" : null,
1613
+ "Int64" : null,
1614
+ "Uint" : null,
1615
+ "Uint8" : null,
1616
+ "Uint16" : null,
1617
+ "Uint32" : null,
1618
+ "Uint64" : null,
1619
+ "Float32" : null,
1620
+ "Float64" : null,
1621
+ "String" : null,
1622
+ "PBool": null,
1623
+ "Map": null,
1624
+ "Slice": null,
1625
+ "Interface": null,
1626
+ "PRaw": null,
1627
+ "PTime": null,
1628
+ "PBigInt": null,
1629
+ "PText": null,
1630
+ "PBuffer": null,
1631
+ "PStruct": null,
1632
+ "Raw": null,
1633
+ "Time": null,
1634
+ "BigInt": null,
1635
+ "Text": null,
1636
+ "Buffer": null,
1637
+ "Struct": null
1638
+ }` )
1639
+ nulls := NullTest {
1640
+ Bool : true ,
1641
+ Int : 2 ,
1642
+ Int8 : 3 ,
1643
+ Int16 : 4 ,
1644
+ Int32 : 5 ,
1645
+ Int64 : 6 ,
1646
+ Uint : 7 ,
1647
+ Uint8 : 8 ,
1648
+ Uint16 : 9 ,
1649
+ Uint32 : 10 ,
1650
+ Uint64 : 11 ,
1651
+ Float32 : 12.1 ,
1652
+ Float64 : 13.1 ,
1653
+ String : "14" ,
1654
+ PBool : new (bool ),
1655
+ Map : map [string ]string {},
1656
+ Slice : []string {},
1657
+ Interface : new (MustNotUnmarshalJSON ),
1658
+ PRaw : new (RawMessage ),
1659
+ PTime : new (time.Time ),
1660
+ PBigInt : new (big.Int ),
1661
+ PText : new (MustNotUnmarshalText ),
1662
+ PStruct : new (struct {}),
1663
+ PBuffer : new (bytes.Buffer ),
1664
+ Raw : RawMessage ("123" ),
1665
+ Time : time .Unix (123456789 , 0 ),
1666
+ BigInt : * big .NewInt (123 ),
1667
+ }
1668
+
1669
+ before := nulls .Time .String ()
1561
1670
1562
1671
err := Unmarshal (jsonData , & nulls )
1563
1672
if err != nil {
@@ -1566,9 +1675,61 @@ func TestUnmarshalNulls(t *testing.T) {
1566
1675
if ! nulls .Bool || nulls .Int != 2 || nulls .Int8 != 3 || nulls .Int16 != 4 || nulls .Int32 != 5 || nulls .Int64 != 6 ||
1567
1676
nulls .Uint != 7 || nulls .Uint8 != 8 || nulls .Uint16 != 9 || nulls .Uint32 != 10 || nulls .Uint64 != 11 ||
1568
1677
nulls .Float32 != 12.1 || nulls .Float64 != 13.1 || nulls .String != "14" {
1569
-
1570
1678
t .Errorf ("Unmarshal of null values affected primitives" )
1571
1679
}
1680
+
1681
+ if nulls .PBool != nil {
1682
+ t .Errorf ("Unmarshal of null did not clear nulls.PBool" )
1683
+ }
1684
+ if nulls .Map != nil {
1685
+ t .Errorf ("Unmarshal of null did not clear nulls.Map" )
1686
+ }
1687
+ if nulls .Slice != nil {
1688
+ t .Errorf ("Unmarshal of null did not clear nulls.Slice" )
1689
+ }
1690
+ if nulls .Interface != nil {
1691
+ t .Errorf ("Unmarshal of null did not clear nulls.Interface" )
1692
+ }
1693
+ if nulls .PRaw != nil {
1694
+ t .Errorf ("Unmarshal of null did not clear nulls.PRaw" )
1695
+ }
1696
+ if nulls .PTime != nil {
1697
+ t .Errorf ("Unmarshal of null did not clear nulls.PTime" )
1698
+ }
1699
+ if nulls .PBigInt != nil {
1700
+ t .Errorf ("Unmarshal of null did not clear nulls.PBigInt" )
1701
+ }
1702
+ if nulls .PText != nil {
1703
+ t .Errorf ("Unmarshal of null did not clear nulls.PText" )
1704
+ }
1705
+ if nulls .PBuffer != nil {
1706
+ t .Errorf ("Unmarshal of null did not clear nulls.PBuffer" )
1707
+ }
1708
+ if nulls .PStruct != nil {
1709
+ t .Errorf ("Unmarshal of null did not clear nulls.PStruct" )
1710
+ }
1711
+
1712
+ if string (nulls .Raw ) != "null" {
1713
+ t .Errorf ("Unmarshal of RawMessage null did not record null: %v" , string (nulls .Raw ))
1714
+ }
1715
+ if nulls .Time .String () != before {
1716
+ t .Errorf ("Unmarshal of time.Time null set time to %v" , nulls .Time .String ())
1717
+ }
1718
+ if nulls .BigInt .String () != "123" {
1719
+ t .Errorf ("Unmarshal of big.Int null set int to %v" , nulls .BigInt .String ())
1720
+ }
1721
+ }
1722
+
1723
+ type MustNotUnmarshalJSON struct {}
1724
+
1725
+ func (x MustNotUnmarshalJSON ) UnmarshalJSON (data []byte ) error {
1726
+ return errors .New ("MustNotUnmarshalJSON was used" )
1727
+ }
1728
+
1729
+ type MustNotUnmarshalText struct {}
1730
+
1731
+ func (x MustNotUnmarshalText ) UnmarshalText (text []byte ) error {
1732
+ return errors .New ("MustNotUnmarshalText was used" )
1572
1733
}
1573
1734
1574
1735
func TestStringKind (t * testing.T ) {
@@ -1807,7 +1968,7 @@ var invalidUnmarshalTextTests = []struct {
1807
1968
{nil , "json: Unmarshal(nil)" },
1808
1969
{struct {}{}, "json: Unmarshal(non-pointer struct {})" },
1809
1970
{(* int )(nil ), "json: Unmarshal(nil *int)" },
1810
- {new (net.IP ), "json: cannot unmarshal string into Go value of type *net.IP" },
1971
+ {new (net.IP ), "json: cannot unmarshal number into Go value of type *net.IP" },
1811
1972
}
1812
1973
1813
1974
func TestInvalidUnmarshalText (t * testing.T ) {
0 commit comments