// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "bytes" "reflect" "strconv" "testing" ) type myStruct struct { T bool F bool S string I8 int8 I16 int16 I32 int32 I64 int64 U8 uint8 U16 uint16 U32 uint32 U64 uint64 I int U uint Fl float Fl32 float32 Fl64 float64 A []string My *myStruct Map map[string][]int MapStruct map[string]myStruct MapPtrStruct map[string]*myStruct } const encoded = `{"t":true,"f":false,"s":"abc","i8":1,"i16":2,"i32":3,"i64":4,` + ` "u8":5,"u16":6,"u32":7,"u64":8,` + ` "i":-9,"u":10,"bogusfield":"should be ignored",` + ` "fl":11.5,"fl32":12.25,"fl64":13.75,` + ` "a":["x","y","z"],"my":{"s":"subguy"},` + `"map":{"k1":[1,2,3],"k2":[],"k3":[3,4]},` + `"mapstruct":{"m1":{"u8":8}},` + `"mapptrstruct":{"m1":{"u8":8}}}` var decodedMap = map[string][]int{ "k1": []int{1, 2, 3}, "k2": []int{}, "k3": []int{3, 4}, } var decodedMapStruct = map[string]myStruct{ "m1": myStruct{U8: 8}, } var decodedMapPtrStruct = map[string]*myStruct{ "m1": &myStruct{U8: 8}, } func check(t *testing.T, ok bool, name string, v interface{}) { if !ok { t.Errorf("%s = %v (BAD)", name, v) } else { t.Logf("%s = %v (good)", name, v) } } const whiteSpaceEncoded = " \t{\n\"s\"\r:\"string\"\v}" func TestUnmarshalWhitespace(t *testing.T) { var m myStruct ok, errtok := Unmarshal(whiteSpaceEncoded, &m) if !ok { t.Fatalf("Unmarshal failed near %s", errtok) } check(t, m.S == "string", "string", m.S) } func TestUnmarshal(t *testing.T) { var m myStruct m.F = true ok, errtok := Unmarshal(encoded, &m) if !ok { t.Fatalf("Unmarshal failed near %s", errtok) } check(t, m.T == true, "t", m.T) check(t, m.F == false, "f", m.F) check(t, m.S == "abc", "s", m.S) check(t, m.I8 == 1, "i8", m.I8) check(t, m.I16 == 2, "i16", m.I16) check(t, m.I32 == 3, "i32", m.I32) check(t, m.I64 == 4, "i64", m.I64) check(t, m.U8 == 5, "u8", m.U8) check(t, m.U16 == 6, "u16", m.U16) check(t, m.U32 == 7, "u32", m.U32) check(t, m.U64 == 8, "u64", m.U64) check(t, m.I == -9, "i", m.I) check(t, m.U == 10, "u", m.U) check(t, m.Fl == 11.5, "fl", m.Fl) check(t, m.Fl32 == 12.25, "fl32", m.Fl32) check(t, m.Fl64 == 13.75, "fl64", m.Fl64) check(t, m.A != nil, "a", m.A) if m.A != nil { check(t, m.A[0] == "x", "a[0]", m.A[0]) check(t, m.A[1] == "y", "a[1]", m.A[1]) check(t, m.A[2] == "z", "a[2]", m.A[2]) } check(t, m.My != nil, "my", m.My) if m.My != nil { check(t, m.My.S == "subguy", "my.s", m.My.S) } check(t, reflect.DeepEqual(m.Map, decodedMap), "map", m.Map) check(t, reflect.DeepEqual(m.MapStruct, decodedMapStruct), "mapstruct", m.MapStruct) check(t, reflect.DeepEqual(m.MapPtrStruct, decodedMapPtrStruct), "mapptrstruct", m.MapPtrStruct) } type Issue147Text struct { Text string } type Issue147 struct { Test []Issue147Text } const issue147Input = `{"test": [{"text":"0"},{"text":"1"},{"text":"2"}, {"text":"3"},{"text":"4"},{"text":"5"}, {"text":"6"},{"text":"7"},{"text":"8"}, {"text":"9"},{"text":"10"},{"text":"11"}, {"text":"12"},{"text":"13"},{"text":"14"}, {"text":"15"},{"text":"16"},{"text":"17"}, {"text":"18"},{"text":"19"},{"text":"20"}, {"text":"21"},{"text":"22"},{"text":"23"}, {"text":"24"},{"text":"25"},{"text":"26"}, {"text":"27"},{"text":"28"},{"text":"29"}]}` func TestIssue147(t *testing.T) { var timeline Issue147 Unmarshal(issue147Input, &timeline) if len(timeline.Test) != 30 { t.Errorf("wrong length: got %d want 30", len(timeline.Test)) } for i, e := range timeline.Test { if e.Text != strconv.Itoa(i) { t.Errorf("index: %d got: %s want: %d", i, e.Text, i) } } } type Issue114 struct { Text string } const issue114Input = `[{"text" : "0"}, {"text" : "1"}, {"text" : "2"}, {"text" : "3"}]` func TestIssue114(t *testing.T) { var items []Issue114 Unmarshal(issue114Input, &items) if len(items) != 4 { t.Errorf("wrong length: got %d want 4", len(items)) } for i, e := range items { if e.Text != strconv.Itoa(i) { t.Errorf("index: %d got: %s want: %d", i, e.Text, i) } } } type marshalTest struct { val interface{} out string } type MTE string type OneField struct { a int } type ScalarWithString int const ( AA ScalarWithString = iota BB CC ) var scalarStrings = []string{"AA", "BB", "CC"} func (x ScalarWithString) String() string { return scalarStrings[x] } var marshalTests = []marshalTest{ // basic string marshalTest{nil, "null"}, marshalTest{true, "true"}, marshalTest{false, "false"}, marshalTest{123, "123"}, marshalTest{0.1, "0.1"}, marshalTest{1e-10, "1e-10"}, marshalTest{"teststring", `"teststring"`}, marshalTest{[4]int{1, 2, 3, 4}, "[1,2,3,4]"}, marshalTest{[]int{1, 2, 3, 4}, "[1,2,3,4]"}, marshalTest{[]interface{}{nil}, "[null]"}, marshalTest{[][]int{[]int{1, 2}, []int{3, 4}}, "[[1,2],[3,4]]"}, marshalTest{map[string]string{"one": "one"}, `{"one":"one"}`}, marshalTest{map[string]int{"one": 1}, `{"one":1}`}, marshalTest{map[string]interface{}{"null": nil}, `{"null":null}`}, marshalTest{struct{}{}, "{}"}, marshalTest{struct{ a int }{1}, `{"a":1}`}, marshalTest{struct{ a interface{} }{nil}, `{"a":null}`}, marshalTest{struct { a int b string }{1, "hello"}, `{"a":1,"b":"hello"}`, }, marshalTest{map[string][]int{"3": []int{1, 2, 3}}, `{"3":[1,2,3]}`}, marshalTest{map[string]*MTE{"hi": nil}, `{"hi":null}`}, marshalTest{map[string]interface{}{"hi": 3}, `{"hi":3}`}, marshalTest{&OneField{3}, `{"a":3}`}, marshalTest{"\x05\x06", `"\u0005\u0006"`}, marshalTest{uintptr(50000), "50000"}, marshalTest{uint64(50000), "50000"}, marshalTest{uint32(50000), "50000"}, marshalTest{uint16(50000), "50000"}, marshalTest{uint8(50), "50"}, marshalTest{int64(50000), "50000"}, marshalTest{int32(50000), "50000"}, marshalTest{int16(10000), "10000"}, marshalTest{int8(50), "50"}, marshalTest{BB, "1"}, } func TestMarshal(t *testing.T) { for _, tt := range marshalTests { var buf bytes.Buffer err := Marshal(&buf, tt.val) if err != nil { t.Fatalf("Marshal(%T): %s", tt.val, err) } s := buf.String() if s != tt.out { t.Errorf("Marshal(%T) = %q, want %q\n", tt.val, s, tt.out) } } } type marshalIndentTest struct { val interface{} indent string out string } const marshalIndentTest1 = `[ 1, 2, 3, 4 ] ` const marshalIndentTest2 = `[ [ 1, 2 ], [ 3, 4 ] ] ` const marshalIndentTest3 = `[ [ 1, 2 ], [ 3, 4 ] ] ` const marshalIndentTest4 = `[ [ 1, 2 ], [ 3, 4 ] ] ` const marshalIndentTest5 = `{ "a":1, "b":"hello" } ` const marshalIndentTest6 = `{ "3":[ 1, 2, 3 ] } ` var marshalIndentTests = []marshalIndentTest{ marshalIndentTest{[]int{1, 2, 3, 4}, " ", marshalIndentTest1}, marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, "", marshalIndentTest2}, marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, " ", marshalIndentTest3}, marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, " ", marshalIndentTest4}, marshalIndentTest{struct { a int b string }{1, "hello"}, " ", marshalIndentTest5, }, marshalIndentTest{map[string][]int{"3": []int{1, 2, 3}}, " ", marshalIndentTest6}, } func TestMarshalIndent(t *testing.T) { for _, tt := range marshalIndentTests { var buf bytes.Buffer err := MarshalIndent(&buf, tt.val, tt.indent) if err != nil { t.Fatalf("MarshalIndent(%v): %s", tt.val, err) } s := buf.String() if s != tt.out { t.Errorf("MarshalIndent(%v) = %q, want %q\n", tt.val, s, tt.out) } } } type marshalErrorTest struct { val interface{} error string } type ChanVal struct { C chan int } var marshalErrorTests = []marshalErrorTest{ marshalErrorTest{map[chan int]string{make(chan int): "one"}, "json cannot encode value of type map[chan int] string"}, marshalErrorTest{make(chan int, 100), "json cannot encode value of type chan int"}, marshalErrorTest{new(ChanVal), "json cannot encode value of type chan int"}, } func TestMarshalError(t *testing.T) { for _, tt := range marshalErrorTests { var buf bytes.Buffer err := Marshal(&buf, tt.val) if err == nil { t.Fatalf("Marshal(%T): no error, want error %s", tt.val, tt.error) } if err.String() != tt.error { t.Fatalf("Marshal(%T) = error %s, want error %s", tt.val, err, tt.error) } } }