-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson.go
139 lines (119 loc) · 3.69 KB
/
json.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package simplejson
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"reflect"
"sync"
)
// Getter is the interface that is returned by the Loads() function. Any new methods that can be used to get/validate values from the json can be used inside Getter.
type Getter interface {
// Get method is to get the value of a json key and also accepts an optional index number.
// If the *data object is a map, it returns the value of the key as x.Get("key1"). The value of index is irrelevant in this case.
// If the *data object is a slice, we need to select the index in one call to Get() as `x.Get("", 0)`
// where the first parameter is irrelevant and 0 indicates the index of the element in the json slice.
// Eg: data := d.Get("Actors").Get("", 0).Get("name")
Get(string, ...int) Getter
// String return the json string representation of the selected key's value (Equivalent to json.Dumps()).
String() string
// Bytes return the marshalled byte representation of the value
Bytes() []byte
}
// jsonData Holds the actual unmarshalled data
type jsonData interface{}
// data holds jsonData and a mutex.
type data struct {
sync.Mutex
jsonData
}
// empty type is used to return an empty value so that users can evaluate the return type.
type empty struct{}
func (e *empty) Get(key string, index ...int) Getter {
return e
}
func (e *empty) Bytes() []byte {
return nil
}
func (e *empty) String() string {
return ""
}
// Loads load a json string and returns a Getter
func Loads(b []byte) (Getter, error) {
j := new(data)
err := j.unmarshalJSON(b)
if err != nil {
return nil, err
}
return j, nil
}
// Dumps returns the string representation of a type.
func Dumps(o interface{}) ([]byte, error) {
return json.Marshal(o)
}
// Load accepts an io.Reader to read the content and unmarshall the json. The called must close the handler passed to this function.
func Load(i io.Reader) (Getter, error) {
d, err := ioutil.ReadAll(i)
if err != nil {
return nil, err
}
return Loads(d)
}
// Get method is to get the value of a json key. Get() also accepts an optional index number.
// If the *data object is a map, it returns the value of the key as x.Get("key1"). The value of index is irrelevant in this case.
// If the *data object is a slice, we need to select the index in one call to Get() as `x.Get("", 0)`
// where the first parameter is irrelevant and 0 indicates the index of the element in the json slice.
// Eg: data := d.Get("Actors").Get("", 0).Get("name")
func (d *data) Get(key string, index ...int) Getter {
d.Lock()
defer d.Unlock()
sliceData := new(data)
sliceData.Lock()
defer sliceData.Unlock()
switch d.jsonData.(type) {
case map[string]interface{}:
if d.jsonData.(map[string]interface{})[key] == nil {
e := new(empty)
return e
}
sliceData.jsonData = d.jsonData.(map[string]interface{})[key]
case []interface{}:
if len(d.jsonData.([]interface{})) < (index[0]) {
e := new(empty)
return e
}
sliceData.jsonData = d.jsonData.([]interface{})[index[0]]
default:
panic(fmt.Errorf("not implemented for %s", reflect.TypeOf(d.jsonData)))
}
return sliceData
}
// String return the json string representation of the selected key's value (Equivalent to json.Dumps()).
func (d *data) String() string {
d.Lock()
defer d.Unlock()
data, err := json.Marshal(d.jsonData)
if err != nil {
panic(err)
}
return fmt.Sprintf("%s", data)
}
// Bytes return the marshalled byte representation of the value
func (d *data) Bytes() []byte {
d.Lock()
defer d.Unlock()
data, err := json.Marshal(d.jsonData)
if err != nil {
panic(err)
}
return data
}
func (d *data) unmarshalJSON(b []byte) error {
d.Lock()
defer d.Unlock()
err := json.Unmarshal(b, &d.jsonData)
if err != nil {
return err
}
return nil
}