go-json/decode_test.go

3092 lines
80 KiB
Go
Raw Normal View History

2020-04-22 07:06:52 +03:00
package json_test
import (
2020-09-17 15:50:27 +03:00
"bytes"
"encoding"
stdjson "encoding/json"
2020-09-17 15:50:27 +03:00
"errors"
2020-04-25 13:55:05 +03:00
"fmt"
2020-09-17 15:50:27 +03:00
"image"
"math"
"math/big"
2020-12-24 14:08:27 +03:00
"net"
2020-05-08 09:13:30 +03:00
"reflect"
2020-09-17 15:50:27 +03:00
"strconv"
2020-05-24 15:31:10 +03:00
"strings"
2020-04-22 07:06:52 +03:00
"testing"
2020-09-17 15:50:27 +03:00
"time"
2021-03-28 20:28:04 +03:00
"unsafe"
2020-04-22 07:06:52 +03:00
"github.com/goccy/go-json"
)
func Test_Decoder(t *testing.T) {
2020-04-24 10:10:07 +03:00
t.Run("int", func(t *testing.T) {
var v int
assertErr(t, json.Unmarshal([]byte(`-1`), &v))
assertEq(t, "int", int(-1), v)
})
t.Run("int8", func(t *testing.T) {
var v int8
assertErr(t, json.Unmarshal([]byte(`-2`), &v))
assertEq(t, "int8", int8(-2), v)
})
t.Run("int16", func(t *testing.T) {
var v int16
assertErr(t, json.Unmarshal([]byte(`-3`), &v))
assertEq(t, "int16", int16(-3), v)
})
t.Run("int32", func(t *testing.T) {
var v int32
assertErr(t, json.Unmarshal([]byte(`-4`), &v))
assertEq(t, "int32", int32(-4), v)
})
t.Run("int64", func(t *testing.T) {
var v int64
assertErr(t, json.Unmarshal([]byte(`-5`), &v))
assertEq(t, "int64", int64(-5), v)
})
t.Run("uint", func(t *testing.T) {
var v uint
assertErr(t, json.Unmarshal([]byte(`1`), &v))
assertEq(t, "uint", uint(1), v)
})
t.Run("uint8", func(t *testing.T) {
var v uint8
assertErr(t, json.Unmarshal([]byte(`2`), &v))
assertEq(t, "uint8", uint8(2), v)
})
t.Run("uint16", func(t *testing.T) {
var v uint16
assertErr(t, json.Unmarshal([]byte(`3`), &v))
assertEq(t, "uint16", uint16(3), v)
})
t.Run("uint32", func(t *testing.T) {
var v uint32
assertErr(t, json.Unmarshal([]byte(`4`), &v))
assertEq(t, "uint32", uint32(4), v)
})
t.Run("uint64", func(t *testing.T) {
var v uint64
assertErr(t, json.Unmarshal([]byte(`5`), &v))
assertEq(t, "uint64", uint64(5), v)
})
t.Run("bool", func(t *testing.T) {
t.Run("true", func(t *testing.T) {
var v bool
assertErr(t, json.Unmarshal([]byte(`true`), &v))
assertEq(t, "bool", true, v)
})
t.Run("false", func(t *testing.T) {
v := true
assertErr(t, json.Unmarshal([]byte(`false`), &v))
assertEq(t, "bool", false, v)
})
})
t.Run("string", func(t *testing.T) {
var v string
assertErr(t, json.Unmarshal([]byte(`"hello"`), &v))
assertEq(t, "string", "hello", v)
})
2020-04-24 10:46:12 +03:00
t.Run("float32", func(t *testing.T) {
2020-04-25 13:55:05 +03:00
var v float32
assertErr(t, json.Unmarshal([]byte(`3.14`), &v))
assertEq(t, "float32", float32(3.14), v)
2020-04-24 10:46:12 +03:00
})
t.Run("float64", func(t *testing.T) {
var v float64
assertErr(t, json.Unmarshal([]byte(`3.14`), &v))
assertEq(t, "float64", float64(3.14), v)
})
2020-04-25 13:55:05 +03:00
t.Run("slice", func(t *testing.T) {
var v []int
assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v))
assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v))
})
t.Run("array", func(t *testing.T) {
var v [4]int
assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v))
assertEq(t, "array", fmt.Sprint([4]int{1, 2, 3, 4}), fmt.Sprint(v))
})
2020-04-25 16:48:16 +03:00
t.Run("map", func(t *testing.T) {
var v map[string]int
assertErr(t, json.Unmarshal([]byte(` { "a": 1, "b": 2, "c": 3, "d": 4 } `), &v))
assertEq(t, "map.a", v["a"], 1)
assertEq(t, "map.b", v["b"], 2)
assertEq(t, "map.c", v["c"], 3)
assertEq(t, "map.d", v["d"], 4)
2020-08-08 07:43:24 +03:00
t.Run("nested map", func(t *testing.T) {
// https://github.com/goccy/go-json/issues/8
content := `
{
"a": {
"nestedA": "value of nested a"
},
"b": {
"nestedB": "value of nested b"
},
"c": {
"nestedC": "value of nested c"
}
}`
var v map[string]interface{}
assertErr(t, json.Unmarshal([]byte(content), &v))
assertEq(t, "length", 3, len(v))
})
2020-04-25 16:48:16 +03:00
})
2020-04-22 07:06:52 +03:00
t.Run("struct", func(t *testing.T) {
2020-04-23 19:39:20 +03:00
type T struct {
AA int `json:"aa"`
BB string `json:"bb"`
CC bool `json:"cc"`
}
2020-04-22 07:06:52 +03:00
var v struct {
2020-04-22 11:59:01 +03:00
A int `json:"abcd"`
B string `json:"str"`
2020-04-22 12:51:42 +03:00
C bool
2020-04-23 19:39:20 +03:00
D *T
2020-04-22 07:06:52 +03:00
}
2020-04-23 19:39:20 +03:00
content := []byte(`
{
"abcd": 123,
"str" : "hello",
"c" : true,
"d" : {
"aa": 2,
"bb": "world",
"cc": true
}
}`)
assertErr(t, json.Unmarshal(content, &v))
2020-04-22 11:59:01 +03:00
assertEq(t, "struct.A", 123, v.A)
assertEq(t, "struct.B", "hello", v.B)
2020-04-22 12:51:42 +03:00
assertEq(t, "struct.C", true, v.C)
2020-04-23 19:39:20 +03:00
assertEq(t, "struct.D.AA", 2, v.D.AA)
2020-04-24 10:10:07 +03:00
assertEq(t, "struct.D.BB", "world", v.D.BB)
assertEq(t, "struct.D.CC", true, v.D.CC)
2020-08-08 07:20:42 +03:00
t.Run("struct.field null", func(t *testing.T) {
2020-08-08 06:21:25 +03:00
var v struct {
A string
2020-08-08 07:20:42 +03:00
B []string
C []int
D map[string]interface{}
E [2]string
F interface{}
2020-08-08 06:21:25 +03:00
}
2020-08-08 07:20:42 +03:00
assertErr(t, json.Unmarshal([]byte(`{"a":null,"b":null,"c":null,"d":null,"e":null,"f":null}`), &v))
assertEq(t, "string", v.A, "")
assertNeq(t, "[]string", v.B, nil)
assertEq(t, "[]string", len(v.B), 0)
assertNeq(t, "[]int", v.C, nil)
assertEq(t, "[]int", len(v.C), 0)
assertNeq(t, "map", v.D, nil)
assertEq(t, "map", len(v.D), 0)
assertNeq(t, "array", v.E, nil)
assertEq(t, "array", len(v.E), 2)
assertEq(t, "interface{}", v.F, nil)
2020-08-08 06:21:25 +03:00
})
2020-04-22 07:06:52 +03:00
})
2020-05-08 09:13:30 +03:00
t.Run("interface", func(t *testing.T) {
t.Run("number", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`10`), &v))
assertEq(t, "interface.kind", "float64", reflect.TypeOf(v).Kind().String())
assertEq(t, "interface", `10`, fmt.Sprint(v))
})
t.Run("string", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`"hello"`), &v))
assertEq(t, "interface.kind", "string", reflect.TypeOf(v).Kind().String())
assertEq(t, "interface", `hello`, fmt.Sprint(v))
})
t.Run("escaped string", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`"he\"llo"`), &v))
assertEq(t, "interface.kind", "string", reflect.TypeOf(v).Kind().String())
assertEq(t, "interface", `he"llo`, fmt.Sprint(v))
})
2020-05-08 09:13:30 +03:00
t.Run("bool", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`true`), &v))
assertEq(t, "interface.kind", "bool", reflect.TypeOf(v).Kind().String())
assertEq(t, "interface", `true`, fmt.Sprint(v))
})
t.Run("slice", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`[1,2,3,4]`), &v))
assertEq(t, "interface.kind", "slice", reflect.TypeOf(v).Kind().String())
assertEq(t, "interface", `[1 2 3 4]`, fmt.Sprint(v))
})
t.Run("map", func(t *testing.T) {
var v interface{}
assertErr(t, json.Unmarshal([]byte(`{"a": 1, "b": "c"}`), &v))
assertEq(t, "interface.kind", "map", reflect.TypeOf(v).Kind().String())
2020-08-25 05:17:38 +03:00
m := v.(map[string]interface{})
2020-05-08 09:13:30 +03:00
assertEq(t, "interface", `1`, fmt.Sprint(m["a"]))
assertEq(t, "interface", `c`, fmt.Sprint(m["b"]))
})
t.Run("null", func(t *testing.T) {
var v interface{}
v = 1
assertErr(t, json.Unmarshal([]byte(`null`), &v))
assertEq(t, "interface", nil, v)
})
})
2020-04-22 07:06:52 +03:00
}
2020-05-08 14:22:57 +03:00
func TestIssue98(t *testing.T) {
data := "[\"\\"
var v interface{}
if err := json.Unmarshal([]byte(data), &v); err == nil {
t.Fatal("expected error")
}
}
2020-08-11 12:04:32 +03:00
func Test_Decoder_UseNumber(t *testing.T) {
dec := json.NewDecoder(strings.NewReader(`{"a": 3.14}`))
dec.UseNumber()
var v map[string]interface{}
assertErr(t, dec.Decode(&v))
assertEq(t, "json.Number", "json.Number", fmt.Sprintf("%T", v["a"]))
}
2020-08-11 13:05:20 +03:00
func Test_Decoder_DisallowUnknownFields(t *testing.T) {
dec := json.NewDecoder(strings.NewReader(`{"x": 1}`))
dec.DisallowUnknownFields()
var v struct {
x int
}
err := dec.Decode(&v)
if err == nil {
t.Fatal("expected unknown field error")
}
if err.Error() != `json: unknown field "x"` {
t.Fatal("expected unknown field error")
}
}
2020-05-08 14:22:57 +03:00
type unmarshalJSON struct {
v int
}
func (u *unmarshalJSON) UnmarshalJSON(b []byte) error {
var v int
if err := json.Unmarshal(b, &v); err != nil {
return err
}
u.v = v
return nil
}
func Test_UnmarshalJSON(t *testing.T) {
t.Run("*struct", func(t *testing.T) {
var v unmarshalJSON
assertErr(t, json.Unmarshal([]byte(`10`), &v))
2020-11-21 20:47:18 +03:00
assertEq(t, "unmarshal", 10, v.v)
2020-05-08 14:22:57 +03:00
})
}
2020-05-08 14:25:49 +03:00
type unmarshalText struct {
v int
}
func (u *unmarshalText) UnmarshalText(b []byte) error {
var v int
if err := json.Unmarshal(b, &v); err != nil {
return err
}
u.v = v
return nil
}
func Test_UnmarshalText(t *testing.T) {
t.Run("*struct", func(t *testing.T) {
var v unmarshalText
2021-02-18 10:49:51 +03:00
assertErr(t, json.Unmarshal([]byte(`"11"`), &v))
2020-05-08 14:25:49 +03:00
assertEq(t, "unmarshal", v.v, 11)
})
}
func Test_InvalidUnmarshalError(t *testing.T) {
t.Run("nil", func(t *testing.T) {
var v *struct{}
err := fmt.Sprint(json.Unmarshal([]byte(`{}`), v))
assertEq(t, "invalid unmarshal error", "json: Unmarshal(nil *struct {})", err)
})
t.Run("non pointer", func(t *testing.T) {
var v int
err := fmt.Sprint(json.Unmarshal([]byte(`{}`), v))
assertEq(t, "invalid unmarshal error", "json: Unmarshal(non-pointer int)", err)
})
}
2020-05-24 15:31:10 +03:00
2020-07-30 16:41:53 +03:00
func Test_Token(t *testing.T) {
dec := json.NewDecoder(strings.NewReader(`{"a": 1, "b": true, "c": [1, "two", null]}`))
cnt := 0
for {
if _, err := dec.Token(); err != nil {
break
}
cnt++
}
if cnt != 12 {
t.Fatal("failed to parse token")
}
}
2020-05-24 15:31:10 +03:00
func Test_DecodeStream(t *testing.T) {
const stream = `
[
{"Name": "Ed", "Text": "Knock knock."},
{"Name": "Sam", "Text": "Who's there?"},
{"Name": "Ed", "Text": "Go fmt."},
{"Name": "Sam", "Text": "Go fmt who?"},
{"Name": "Ed", "Text": "Go fmt yourself!"}
]
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(stream))
tk, err := dec.Token()
assertErr(t, err)
assertEq(t, "[", fmt.Sprint(tk), "[")
elem := 0
// while the array contains values
for dec.More() {
var m Message
// decode an array value (Message)
assertErr(t, dec.Decode(&m))
if m.Name == "" || m.Text == "" {
t.Fatal("failed to assign value to struct field")
}
elem++
}
assertEq(t, "decode count", elem, 5)
tk, err = dec.Token()
assertErr(t, err)
assertEq(t, "]", fmt.Sprint(tk), "]")
}
2020-09-17 15:50:27 +03:00
type T struct {
X string
Y int
Z int `json:"-"`
}
type U struct {
Alphabet string `json:"alpha"`
}
type V struct {
F1 interface{}
F2 int32
F3 json.Number
F4 *VOuter
}
type VOuter struct {
V V
}
type W struct {
S SS
}
type P struct {
PP PP
}
type PP struct {
T T
Ts []T
}
type SS string
func (*SS) UnmarshalJSON(data []byte) error {
return &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(SS(""))}
}
// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
// without UseNumber
var ifaceNumAsFloat64 = map[string]interface{}{
"k1": float64(1),
"k2": "s",
"k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
"k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
}
var ifaceNumAsNumber = map[string]interface{}{
"k1": json.Number("1"),
"k2": "s",
"k3": []interface{}{json.Number("1"), json.Number("2.0"), json.Number("3e-3")},
"k4": map[string]interface{}{"kk1": "s", "kk2": json.Number("2")},
}
type tx struct {
x int
}
type u8 uint8
// A type that can unmarshal itself.
type unmarshaler struct {
T bool
}
func (u *unmarshaler) UnmarshalJSON(b []byte) error {
*u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
return nil
}
type ustruct struct {
M unmarshaler
}
var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
type ustructText struct {