1// Package simplejson provides a wrapper for arbitrary JSON objects that adds methods to access properties.
2// Use of this package in place of types and the standard library's encoding/json package is strongly discouraged.
3//
4// Don't lint for stale code, since it's a copied library and we might as well keep the whole thing.
5// nolint:unused
6package simplejson
7
8import (
9	"bytes"
10	"encoding/json"
11	"errors"
12	"log"
13)
14
15// returns the current implementation version
16func Version() string {
17	return "0.5.0"
18}
19
20type Json struct {
21	data interface{}
22}
23
24func (j *Json) FromDB(data []byte) error {
25	j.data = make(map[string]interface{})
26
27	dec := json.NewDecoder(bytes.NewBuffer(data))
28	dec.UseNumber()
29	return dec.Decode(&j.data)
30}
31
32func (j *Json) ToDB() ([]byte, error) {
33	if j == nil || j.data == nil {
34		return nil, nil
35	}
36
37	return j.Encode()
38}
39
40// NewJson returns a pointer to a new `Json` object
41// after unmarshaling `body` bytes
42func NewJson(body []byte) (*Json, error) {
43	j := new(Json)
44	err := j.UnmarshalJSON(body)
45	if err != nil {
46		return nil, err
47	}
48	return j, nil
49}
50
51// New returns a pointer to a new, empty `Json` object
52func New() *Json {
53	return &Json{
54		data: make(map[string]interface{}),
55	}
56}
57
58// NewFromAny returns a pointer to a new `Json` object with provided data.
59func NewFromAny(data interface{}) *Json {
60	return &Json{data: data}
61}
62
63// Interface returns the underlying data
64func (j *Json) Interface() interface{} {
65	return j.data
66}
67
68// Encode returns its marshaled data as `[]byte`
69func (j *Json) Encode() ([]byte, error) {
70	return j.MarshalJSON()
71}
72
73// EncodePretty returns its marshaled data as `[]byte` with indentation
74func (j *Json) EncodePretty() ([]byte, error) {
75	return json.MarshalIndent(&j.data, "", "  ")
76}
77
78// Implements the json.Marshaler interface.
79func (j *Json) MarshalJSON() ([]byte, error) {
80	return json.Marshal(&j.data)
81}
82
83// Set modifies `Json` map by `key` and `value`
84// Useful for changing single key/value in a `Json` object easily.
85func (j *Json) Set(key string, val interface{}) {
86	m, err := j.Map()
87	if err != nil {
88		return
89	}
90	m[key] = val
91}
92
93// SetPath modifies `Json`, recursively checking/creating map keys for the supplied path,
94// and then finally writing in the value
95func (j *Json) SetPath(branch []string, val interface{}) {
96	if len(branch) == 0 {
97		j.data = val
98		return
99	}
100
101	// in order to insert our branch, we need map[string]interface{}
102	if _, ok := (j.data).(map[string]interface{}); !ok {
103		// have to replace with something suitable
104		j.data = make(map[string]interface{})
105	}
106	curr := j.data.(map[string]interface{})
107
108	for i := 0; i < len(branch)-1; i++ {
109		b := branch[i]
110		// key exists?
111		if _, ok := curr[b]; !ok {
112			n := make(map[string]interface{})
113			curr[b] = n
114			curr = n
115			continue
116		}
117
118		// make sure the value is the right sort of thing
119		if _, ok := curr[b].(map[string]interface{}); !ok {
120			// have to replace with something suitable
121			n := make(map[string]interface{})
122			curr[b] = n
123		}
124
125		curr = curr[b].(map[string]interface{})
126	}
127
128	// add remaining k/v
129	curr[branch[len(branch)-1]] = val
130}
131
132// Del modifies `Json` map by deleting `key` if it is present.
133func (j *Json) Del(key string) {
134	m, err := j.Map()
135	if err != nil {
136		return
137	}
138	delete(m, key)
139}
140
141// Get returns a pointer to a new `Json` object
142// for `key` in its `map` representation
143//
144// useful for chaining operations (to traverse a nested JSON):
145//    js.Get("top_level").Get("dict").Get("value").Int()
146func (j *Json) Get(key string) *Json {
147	m, err := j.Map()
148	if err == nil {
149		if val, ok := m[key]; ok {
150			return &Json{val}
151		}
152	}
153	return &Json{nil}
154}
155
156// GetPath searches for the item as specified by the branch
157// without the need to deep dive using Get()'s.
158//
159//   js.GetPath("top_level", "dict")
160func (j *Json) GetPath(branch ...string) *Json {
161	jin := j
162	for _, p := range branch {
163		jin = jin.Get(p)
164	}
165	return jin
166}
167
168// GetIndex returns a pointer to a new `Json` object
169// for `index` in its `array` representation
170//
171// this is the analog to Get when accessing elements of
172// a json array instead of a json object:
173//    js.Get("top_level").Get("array").GetIndex(1).Get("key").Int()
174func (j *Json) GetIndex(index int) *Json {
175	a, err := j.Array()
176	if err == nil {
177		if len(a) > index {
178			return &Json{a[index]}
179		}
180	}
181	return &Json{nil}
182}
183
184// SetIndex modifies `Json` array by `index` and `value`
185// for `index` in its `array` representation
186func (j *Json) SetIndex(index int, val interface{}) {
187	a, err := j.Array()
188	if err == nil {
189		if len(a) > index {
190			a[index] = val
191		}
192	}
193}
194
195// CheckGet returns a pointer to a new `Json` object and
196// a `bool` identifying success or failure
197//
198// useful for chained operations when success is important:
199//    if data, ok := js.Get("top_level").CheckGet("inner"); ok {
200//        log.Println(data)
201//    }
202func (j *Json) CheckGet(key string) (*Json, bool) {
203	m, err := j.Map()
204	if err == nil {
205		if val, ok := m[key]; ok {
206			return &Json{val}, true
207		}
208	}
209	return nil, false
210}
211
212// Map type asserts to `map`
213func (j *Json) Map() (map[string]interface{}, error) {
214	if m, ok := (j.data).(map[string]interface{}); ok {
215		return m, nil
216	}
217	return nil, errors.New("type assertion to map[string]interface{} failed")
218}
219
220// Array type asserts to an `array`
221func (j *Json) Array() ([]interface{}, error) {
222	if a, ok := (j.data).([]interface{}); ok {
223		return a, nil
224	}
225	return nil, errors.New("type assertion to []interface{} failed")
226}
227
228// Bool type asserts to `bool`
229func (j *Json) Bool() (bool, error) {
230	if s, ok := (j.data).(bool); ok {
231		return s, nil
232	}
233	return false, errors.New("type assertion to bool failed")
234}
235
236// String type asserts to `string`
237func (j *Json) String() (string, error) {
238	if s, ok := (j.data).(string); ok {
239		return s, nil
240	}
241	return "", errors.New("type assertion to string failed")
242}
243
244// Bytes type asserts to `[]byte`
245func (j *Json) Bytes() ([]byte, error) {
246	if s, ok := (j.data).(string); ok {
247		return []byte(s), nil
248	}
249	return nil, errors.New("type assertion to []byte failed")
250}
251
252// StringArray type asserts to an `array` of `string`
253func (j *Json) StringArray() ([]string, error) {
254	arr, err := j.Array()
255	if err != nil {
256		return nil, err
257	}
258	retArr := make([]string, 0, len(arr))
259	for _, a := range arr {
260		if a == nil {
261			retArr = append(retArr, "")
262			continue
263		}
264		s, ok := a.(string)
265		if !ok {
266			return nil, err
267		}
268		retArr = append(retArr, s)
269	}
270	return retArr, nil
271}
272
273// MustArray guarantees the return of a `[]interface{}` (with optional default)
274//
275// useful when you want to iterate over array values in a succinct manner:
276//		for i, v := range js.Get("results").MustArray() {
277//			fmt.Println(i, v)
278//		}
279func (j *Json) MustArray(args ...[]interface{}) []interface{} {
280	var def []interface{}
281
282	switch len(args) {
283	case 0:
284	case 1:
285		def = args[0]
286	default:
287		log.Panicf("MustArray() received too many arguments %d", len(args))
288	}
289
290	a, err := j.Array()
291	if err == nil {
292		return a
293	}
294
295	return def
296}
297
298// MustMap guarantees the return of a `map[string]interface{}` (with optional default)
299//
300// useful when you want to iterate over map values in a succinct manner:
301//		for k, v := range js.Get("dictionary").MustMap() {
302//			fmt.Println(k, v)
303//		}
304func (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{} {
305	var def map[string]interface{}
306
307	switch len(args) {
308	case 0:
309	case 1:
310		def = args[0]
311	default:
312		log.Panicf("MustMap() received too many arguments %d", len(args))
313	}
314
315	a, err := j.Map()
316	if err == nil {
317		return a
318	}
319
320	return def
321}
322
323// MustString guarantees the return of a `string` (with optional default)
324//
325// useful when you explicitly want a `string` in a single value return context:
326//     myFunc(js.Get("param1").MustString(), js.Get("optional_param").MustString("my_default"))
327func (j *Json) MustString(args ...string) string {
328	var def string
329
330	switch len(args) {
331	case 0:
332	case 1:
333		def = args[0]
334	default:
335		log.Panicf("MustString() received too many arguments %d", len(args))
336	}
337
338	s, err := j.String()
339	if err == nil {
340		return s
341	}
342
343	return def
344}
345
346// MustStringArray guarantees the return of a `[]string` (with optional default)
347//
348// useful when you want to iterate over array values in a succinct manner:
349//		for i, s := range js.Get("results").MustStringArray() {
350//			fmt.Println(i, s)
351//		}
352func (j *Json) MustStringArray(args ...[]string) []string {
353	var def []string
354
355	switch len(args) {
356	case 0:
357	case 1:
358		def = args[0]
359	default:
360		log.Panicf("MustStringArray() received too many arguments %d", len(args))
361	}
362
363	a, err := j.StringArray()
364	if err == nil {
365		return a
366	}
367
368	return def
369}
370
371// MustInt guarantees the return of an `int` (with optional default)
372//
373// useful when you explicitly want an `int` in a single value return context:
374//     myFunc(js.Get("param1").MustInt(), js.Get("optional_param").MustInt(5150))
375func (j *Json) MustInt(args ...int) int {
376	var def int
377
378	switch len(args) {
379	case 0:
380	case 1:
381		def = args[0]
382	default:
383		log.Panicf("MustInt() received too many arguments %d", len(args))
384	}
385
386	i, err := j.Int()
387	if err == nil {
388		return i
389	}
390
391	return def
392}
393
394// MustFloat64 guarantees the return of a `float64` (with optional default)
395//
396// useful when you explicitly want a `float64` in a single value return context:
397//     myFunc(js.Get("param1").MustFloat64(), js.Get("optional_param").MustFloat64(5.150))
398func (j *Json) MustFloat64(args ...float64) float64 {
399	var def float64
400
401	switch len(args) {
402	case 0:
403	case 1:
404		def = args[0]
405	default:
406		log.Panicf("MustFloat64() received too many arguments %d", len(args))
407	}
408
409	f, err := j.Float64()
410	if err == nil {
411		return f
412	}
413
414	return def
415}
416
417// MustBool guarantees the return of a `bool` (with optional default)
418//
419// useful when you explicitly want a `bool` in a single value return context:
420//     myFunc(js.Get("param1").MustBool(), js.Get("optional_param").MustBool(true))
421func (j *Json) MustBool(args ...bool) bool {
422	var def bool
423
424	switch len(args) {
425	case 0:
426	case 1:
427		def = args[0]
428	default:
429		log.Panicf("MustBool() received too many arguments %d", len(args))
430	}
431
432	b, err := j.Bool()
433	if err == nil {
434		return b
435	}
436
437	return def
438}
439
440// MustInt64 guarantees the return of an `int64` (with optional default)
441//
442// useful when you explicitly want an `int64` in a single value return context:
443//     myFunc(js.Get("param1").MustInt64(), js.Get("optional_param").MustInt64(5150))
444func (j *Json) MustInt64(args ...int64) int64 {
445	var def int64
446
447	switch len(args) {
448	case 0:
449	case 1:
450		def = args[0]
451	default:
452		log.Panicf("MustInt64() received too many arguments %d", len(args))
453	}
454
455	i, err := j.Int64()
456	if err == nil {
457		return i
458	}
459
460	return def
461}
462
463// MustUInt64 guarantees the return of an `uint64` (with optional default)
464//
465// useful when you explicitly want an `uint64` in a single value return context:
466//     myFunc(js.Get("param1").MustUint64(), js.Get("optional_param").MustUint64(5150))
467func (j *Json) MustUint64(args ...uint64) uint64 {
468	var def uint64
469
470	switch len(args) {
471	case 0:
472	case 1:
473		def = args[0]
474	default:
475		log.Panicf("MustUint64() received too many arguments %d", len(args))
476	}
477
478	i, err := j.Uint64()
479	if err == nil {
480		return i
481	}
482
483	return def
484}
485
486// MarshalYAML implements yaml.Marshaller.
487func (j *Json) MarshalYAML() (interface{}, error) {
488	return j.data, nil
489}
490
491// UnmarshalYAML implements yaml.Unmarshaller.
492func (j *Json) UnmarshalYAML(unmarshal func(interface{}) error) error {
493	var data interface{}
494	if err := unmarshal(&data); err != nil {
495		return err
496	}
497	j.data = data
498	return nil
499}
500