1package simplejson
2
3import (
4	"encoding/json"
5	"testing"
6
7	"github.com/bmizerany/assert"
8)
9
10func TestSimplejson(t *testing.T) {
11	var ok bool
12	var err error
13
14	js, err := NewJson([]byte(`{
15		"test": {
16			"string_array": ["asdf", "ghjk", "zxcv"],
17			"string_array_null": ["abc", null, "efg"],
18			"array": [1, "2", 3],
19			"arraywithsubs": [{"subkeyone": 1},
20			{"subkeytwo": 2, "subkeythree": 3}],
21			"int": 10,
22			"float": 5.150,
23			"string": "simplejson",
24			"bool": true,
25			"sub_obj": {"a": 1}
26		}
27	}`))
28
29	assert.NotEqual(t, nil, js)
30	assert.Equal(t, nil, err)
31
32	_, ok = js.CheckGet("test")
33	assert.Equal(t, true, ok)
34
35	_, ok = js.CheckGet("missing_key")
36	assert.Equal(t, false, ok)
37
38	aws := js.Get("test").Get("arraywithsubs")
39	assert.NotEqual(t, nil, aws)
40	var awsval int
41	awsval, _ = aws.GetIndex(0).Get("subkeyone").Int()
42	assert.Equal(t, 1, awsval)
43	awsval, _ = aws.GetIndex(1).Get("subkeytwo").Int()
44	assert.Equal(t, 2, awsval)
45	awsval, _ = aws.GetIndex(1).Get("subkeythree").Int()
46	assert.Equal(t, 3, awsval)
47
48	i, _ := js.Get("test").Get("int").Int()
49	assert.Equal(t, 10, i)
50
51	f, _ := js.Get("test").Get("float").Float64()
52	assert.Equal(t, 5.150, f)
53
54	s, _ := js.Get("test").Get("string").String()
55	assert.Equal(t, "simplejson", s)
56
57	b, _ := js.Get("test").Get("bool").Bool()
58	assert.Equal(t, true, b)
59
60	mi := js.Get("test").Get("int").MustInt()
61	assert.Equal(t, 10, mi)
62
63	mi2 := js.Get("test").Get("missing_int").MustInt(5150)
64	assert.Equal(t, 5150, mi2)
65
66	ms := js.Get("test").Get("string").MustString()
67	assert.Equal(t, "simplejson", ms)
68
69	ms2 := js.Get("test").Get("missing_string").MustString("fyea")
70	assert.Equal(t, "fyea", ms2)
71
72	ma2 := js.Get("test").Get("missing_array").MustArray([]interface{}{"1", 2, "3"})
73	assert.Equal(t, ma2, []interface{}{"1", 2, "3"})
74
75	msa := js.Get("test").Get("string_array").MustStringArray()
76	assert.Equal(t, msa[0], "asdf")
77	assert.Equal(t, msa[1], "ghjk")
78	assert.Equal(t, msa[2], "zxcv")
79
80	msa2 := js.Get("test").Get("string_array").MustStringArray([]string{"1", "2", "3"})
81	assert.Equal(t, msa2[0], "asdf")
82	assert.Equal(t, msa2[1], "ghjk")
83	assert.Equal(t, msa2[2], "zxcv")
84
85	msa3 := js.Get("test").Get("missing_array").MustStringArray([]string{"1", "2", "3"})
86	assert.Equal(t, msa3, []string{"1", "2", "3"})
87
88	mm2 := js.Get("test").Get("missing_map").MustMap(map[string]interface{}{"found": false})
89	assert.Equal(t, mm2, map[string]interface{}{"found": false})
90
91	strs, err := js.Get("test").Get("string_array").StringArray()
92	assert.Equal(t, err, nil)
93	assert.Equal(t, strs[0], "asdf")
94	assert.Equal(t, strs[1], "ghjk")
95	assert.Equal(t, strs[2], "zxcv")
96
97	strs2, err := js.Get("test").Get("string_array_null").StringArray()
98	assert.Equal(t, err, nil)
99	assert.Equal(t, strs2[0], "abc")
100	assert.Equal(t, strs2[1], "")
101	assert.Equal(t, strs2[2], "efg")
102
103	gp, _ := js.GetPath("test", "string").String()
104	assert.Equal(t, "simplejson", gp)
105
106	gp2, _ := js.GetPath("test", "int").Int()
107	assert.Equal(t, 10, gp2)
108
109	assert.Equal(t, js.Get("test").Get("bool").MustBool(), true)
110
111	js.Set("float2", 300.0)
112	assert.Equal(t, js.Get("float2").MustFloat64(), 300.0)
113
114	js.Set("test2", "setTest")
115	assert.Equal(t, "setTest", js.Get("test2").MustString())
116
117	js.Del("test2")
118	assert.NotEqual(t, "setTest", js.Get("test2").MustString())
119
120	js.Get("test").Get("sub_obj").Set("a", 2)
121	assert.Equal(t, 2, js.Get("test").Get("sub_obj").Get("a").MustInt())
122
123	js.GetPath("test", "sub_obj").Set("a", 3)
124	assert.Equal(t, 3, js.GetPath("test", "sub_obj", "a").MustInt())
125}
126
127func TestStdlibInterfaces(t *testing.T) {
128	val := new(struct {
129		Name   string `json:"name"`
130		Params *Json  `json:"params"`
131	})
132	val2 := new(struct {
133		Name   string `json:"name"`
134		Params *Json  `json:"params"`
135	})
136
137	raw := `{"name":"myobject","params":{"string":"simplejson"}}`
138
139	assert.Equal(t, nil, json.Unmarshal([]byte(raw), val))
140
141	assert.Equal(t, "myobject", val.Name)
142	assert.NotEqual(t, nil, val.Params.data)
143	s, _ := val.Params.Get("string").String()
144	assert.Equal(t, "simplejson", s)
145
146	p, err := json.Marshal(val)
147	assert.Equal(t, nil, err)
148	assert.Equal(t, nil, json.Unmarshal(p, val2))
149	assert.Equal(t, val, val2) // stable
150}
151
152func TestSet(t *testing.T) {
153	js, err := NewJson([]byte(`{}`))
154	assert.Equal(t, nil, err)
155
156	js.Set("baz", "bing")
157
158	s, err := js.GetPath("baz").String()
159	assert.Equal(t, nil, err)
160	assert.Equal(t, "bing", s)
161}
162
163func TestReplace(t *testing.T) {
164	js, err := NewJson([]byte(`{}`))
165	assert.Equal(t, nil, err)
166
167	err = js.UnmarshalJSON([]byte(`{"baz":"bing"}`))
168	assert.Equal(t, nil, err)
169
170	s, err := js.GetPath("baz").String()
171	assert.Equal(t, nil, err)
172	assert.Equal(t, "bing", s)
173}
174
175func TestSetPath(t *testing.T) {
176	js, err := NewJson([]byte(`{}`))
177	assert.Equal(t, nil, err)
178
179	js.SetPath([]string{"foo", "bar"}, "baz")
180
181	s, err := js.GetPath("foo", "bar").String()
182	assert.Equal(t, nil, err)
183	assert.Equal(t, "baz", s)
184}
185
186func TestSetPathNoPath(t *testing.T) {
187	js, err := NewJson([]byte(`{"some":"data","some_number":1.0,"some_bool":false}`))
188	assert.Equal(t, nil, err)
189
190	f := js.GetPath("some_number").MustFloat64(99.0)
191	assert.Equal(t, f, 1.0)
192
193	js.SetPath([]string{}, map[string]interface{}{"foo": "bar"})
194
195	s, err := js.GetPath("foo").String()
196	assert.Equal(t, nil, err)
197	assert.Equal(t, "bar", s)
198
199	f = js.GetPath("some_number").MustFloat64(99.0)
200	assert.Equal(t, f, 99.0)
201}
202
203func TestPathWillAugmentExisting(t *testing.T) {
204	js, err := NewJson([]byte(`{"this":{"a":"aa","b":"bb","c":"cc"}}`))
205	assert.Equal(t, nil, err)
206
207	js.SetPath([]string{"this", "d"}, "dd")
208
209	cases := []struct {
210		path    []string
211		outcome string
212	}{
213		{
214			path:    []string{"this", "a"},
215			outcome: "aa",
216		},
217		{
218			path:    []string{"this", "b"},
219			outcome: "bb",
220		},
221		{
222			path:    []string{"this", "c"},
223			outcome: "cc",
224		},
225		{
226			path:    []string{"this", "d"},
227			outcome: "dd",
228		},
229	}
230
231	for _, tc := range cases {
232		s, err := js.GetPath(tc.path...).String()
233		assert.Equal(t, nil, err)
234		assert.Equal(t, tc.outcome, s)
235	}
236}
237
238func TestPathWillOverwriteExisting(t *testing.T) {
239	// notice how "a" is 0.1 - but then we'll try to set at path a, foo
240	js, err := NewJson([]byte(`{"this":{"a":0.1,"b":"bb","c":"cc"}}`))
241	assert.Equal(t, nil, err)
242
243	js.SetPath([]string{"this", "a", "foo"}, "bar")
244
245	s, err := js.GetPath("this", "a", "foo").String()
246	assert.Equal(t, nil, err)
247	assert.Equal(t, "bar", s)
248}
249