initial commit
[govpp.git] / vendor / github.com / bennyscetbun / jsongo / jsongo.go
1 // Copyright 2014 Benny Scetbun. All rights reserved.
2 // Use of this source code is governed by a MIT-style
3 // license that can be found in the LICENSE file.
4
5 // Package Jsongo is a simple library to help you build Json without static struct
6 //
7 // Source code and project home:
8 // https://github.com/benny-deluxe/jsongo
9 //
10
11 package jsongo
12
13 import (
14         "encoding/json"
15         "errors"
16         "reflect"
17         //"fmt"
18 )
19
20 //ErrorKeyAlreadyExist error if a key already exist in current JSONNode
21 var ErrorKeyAlreadyExist = errors.New("jsongo key already exist")
22
23 //ErrorMultipleType error if a JSONNode already got a different type of value
24 var ErrorMultipleType = errors.New("jsongo this node is already set to a different jsonNodeType")
25
26 //ErrorArrayNegativeValue error if you ask for a negative index in an array
27 var ErrorArrayNegativeValue = errors.New("jsongo negative index for array")
28
29 //ErrorArrayNegativeValue error if you ask for a negative index in an array
30 var ErrorAtUnsupportedType = errors.New("jsongo Unsupported Type as At argument")
31
32 //ErrorRetrieveUserValue error if you ask the value of a node that is not a value node
33 var ErrorRetrieveUserValue = errors.New("jsongo Cannot retrieve node's value which is not of type value")
34
35 //ErrorTypeUnmarshaling error if you try to unmarshal something in the wrong type
36 var ErrorTypeUnmarshaling = errors.New("jsongo Wrong type when Unmarshaling")
37
38 //ErrorUnknowType error if you try to use an unknow JSONNodeType
39 var ErrorUnknowType = errors.New("jsongo Unknow JSONNodeType")
40
41 //ErrorValNotPointer error if you try to use Val without a valid pointer
42 var ErrorValNotPointer = errors.New("jsongo: Val: arguments must be a pointer and not nil")
43
44 //ErrorGetKeys error if you try to get the keys from a JSONNode that isnt a TypeMap or a TypeArray
45 var ErrorGetKeys = errors.New("jsongo: GetKeys: JSONNode is not a TypeMap or TypeArray")
46
47 //ErrorDeleteKey error if you try to call DelKey on a JSONNode that isnt a TypeMap
48 var ErrorDeleteKey = errors.New("jsongo: DelKey: This JSONNode is not a TypeMap")
49
50 //ErrorCopyType error if you try to call Copy on a JSONNode that isnt a TypeUndefined
51 var ErrorCopyType = errors.New("jsongo: Copy: This JSONNode is not a TypeUndefined")
52
53 //JSONNode Datastructure to build and maintain Nodes
54 type JSONNode struct {
55         m          map[string]*JSONNode
56         a          []JSONNode
57         v          interface{}
58         vChanged   bool         //True if we changed the type of the value
59         t          JSONNodeType //Type of that JSONNode 0: Not defined, 1: map, 2: array, 3: value
60         dontExpand bool         //dont expand while Unmarshal
61 }
62
63 //JSONNodeType is used to set, check and get the inner type of a JSONNode
64 type JSONNodeType uint
65
66 const (
67         //TypeUndefined is set by default for empty JSONNode
68         TypeUndefined JSONNodeType = iota
69         //TypeMap is set when a JSONNode is a Map
70         TypeMap
71         //TypeArray is set when a JSONNode is an Array
72         TypeArray
73         //TypeValue is set when a JSONNode is a Value Node
74         TypeValue
75         //typeError help us detect errors
76         typeError
77 )
78
79 //At helps you move through your node by building them on the fly
80 //
81 //val can be string or int only
82 //
83 //strings are keys for TypeMap
84 //
85 //ints are index in TypeArray (it will make array grow on the fly, so you should start to populate with the biggest index first)*
86 func (that *JSONNode) At(val ...interface{}) *JSONNode {
87         if len(val) == 0 {
88                 return that
89         }
90         switch vv := val[0].(type) {
91         case string:
92                 return that.atMap(vv, val[1:]...)
93         case int:
94                 return that.atArray(vv, val[1:]...)
95         }
96         panic(ErrorAtUnsupportedType)
97 }
98
99 //atMap return the JSONNode in current map
100 func (that *JSONNode) atMap(key string, val ...interface{}) *JSONNode {
101         if that.t != TypeUndefined && that.t != TypeMap {
102                 panic(ErrorMultipleType)
103         }
104         if that.m == nil {
105                 that.m = make(map[string]*JSONNode)
106                 that.t = TypeMap
107         }
108         if next, ok := that.m[key]; ok {
109                 return next.At(val...)
110         }
111         that.m[key] = new(JSONNode)
112         return that.m[key].At(val...)
113 }
114
115 //atArray return the JSONNode in current TypeArray (and make it grow if necessary)
116 func (that *JSONNode) atArray(key int, val ...interface{}) *JSONNode {
117         if that.t == TypeUndefined {
118                 that.t = TypeArray
119         } else if that.t != TypeArray {
120                 panic(ErrorMultipleType)
121         }
122         if key < 0 {
123                 panic(ErrorArrayNegativeValue)
124         }
125         if key >= len(that.a) {
126                 newa := make([]JSONNode, key+1)
127                 for i := 0; i < len(that.a); i++ {
128                         newa[i] = that.a[i]
129                 }
130                 that.a = newa
131         }
132         return that.a[key].At(val...)
133 }
134
135 //Map Turn this JSONNode to a TypeMap and/or Create a new element for key if necessary and return it
136 func (that *JSONNode) Map(key string) *JSONNode {
137         if that.t != TypeUndefined && that.t != TypeMap {
138                 panic(ErrorMultipleType)
139         }
140         if that.m == nil {
141                 that.m = make(map[string]*JSONNode)
142                 that.t = TypeMap
143         }
144         if _, ok := that.m[key]; ok {
145                 return that.m[key]
146         }
147         that.m[key] = &JSONNode{}
148         return that.m[key]
149 }
150
151 //Array Turn this JSONNode to a TypeArray and/or set the array size (reducing size will make you loose data)
152 func (that *JSONNode) Array(size int) *[]JSONNode {
153         if that.t == TypeUndefined {
154                 that.t = TypeArray
155         } else if that.t != TypeArray {
156                 panic(ErrorMultipleType)
157         }
158         if size < 0 {
159                 panic(ErrorArrayNegativeValue)
160         }
161         var min int
162         if size < len(that.a) {
163                 min = size
164         } else {
165                 min = len(that.a)
166         }
167         newa := make([]JSONNode, size)
168         for i := 0; i < min; i++ {
169                 newa[i] = that.a[i]
170         }
171         that.a = newa
172         return &(that.a)
173 }
174
175 //Val Turn this JSONNode to Value type and/or set that value to val
176 func (that *JSONNode) Val(val interface{}) {
177         if that.t == TypeUndefined {
178                 that.t = TypeValue
179         } else if that.t != TypeValue {
180                 panic(ErrorMultipleType)
181         }
182         rt := reflect.TypeOf(val)
183         var finalval interface{}
184         if val == nil {
185                 finalval = &val
186                 that.vChanged = true
187         } else if rt.Kind() != reflect.Ptr {
188                 rv := reflect.ValueOf(val)
189                 var tmp reflect.Value
190                 if rv.CanAddr() {
191                         tmp = rv.Addr()
192                 } else {
193                         tmp = reflect.New(rt)
194                         tmp.Elem().Set(rv)
195                 }
196                 finalval = tmp.Interface()
197                 that.vChanged = true
198         } else {
199                 finalval = val
200         }
201         that.v = finalval
202 }
203
204 //Get Return value of a TypeValue as interface{}
205 func (that *JSONNode) Get() interface{} {
206         if that.t != TypeValue {
207                 panic(ErrorRetrieveUserValue)
208         }
209         if that.vChanged {
210                 rv := reflect.ValueOf(that.v)
211                 return rv.Elem().Interface()
212         }
213         return that.v
214 }
215
216 //GetKeys Return a slice interface that represent the keys to use with the At fonction (Works only on TypeMap and TypeArray)
217 func (that *JSONNode) GetKeys() []interface{} {
218         var ret []interface{}
219         switch that.t {
220         case TypeMap:
221                 nb := len(that.m)
222                 ret = make([]interface{}, nb)
223                 for key := range that.m {
224                         nb--
225                         ret[nb] = key
226                 }
227         case TypeArray:
228                 nb := len(that.a)
229                 ret = make([]interface{}, nb)
230                 for nb > 0 {
231                         nb--
232                         ret[nb] = nb
233                 }
234         default:
235                 panic(ErrorGetKeys)
236         }
237         return ret
238 }
239
240 //Len Return the length of the current Node
241 //
242 // if TypeUndefined return 0
243 //
244 // if TypeValue return 1
245 //
246 // if TypeArray return the size of the array
247 //
248 // if TypeMap return the size of the map
249 func (that *JSONNode) Len() int {
250         var ret int
251         switch that.t {
252         case TypeMap:
253                 ret = len(that.m)
254         case TypeArray:
255                 ret = len(that.a)
256         case TypeValue:
257                 ret = 1
258         }
259         return ret
260 }
261
262 //SetType Is use to set the Type of a node and return the current Node you are working on
263 func (that *JSONNode) SetType(t JSONNodeType) *JSONNode {
264         if that.t != TypeUndefined && that.t != t {
265                 panic(ErrorMultipleType)
266         }
267         if t >= typeError {
268                 panic(ErrorUnknowType)
269         }
270         that.t = t
271         switch t {
272         case TypeMap:
273                 that.m = make(map[string]*JSONNode, 0)
274         case TypeArray:
275                 that.a = make([]JSONNode, 0)
276         case TypeValue:
277                 that.Val(nil)
278         }
279         return that
280 }
281
282 //GetType Is use to Get the Type of a node
283 func (that *JSONNode) GetType() JSONNodeType {
284         return that.t
285 }
286
287 //Copy Will set this node like the one in argument. this node must be of type TypeUndefined
288 //
289 //if deepCopy is true we will copy all the children recursively else we will share the children
290 //
291 //return the current JSONNode
292 func (that *JSONNode) Copy(other *JSONNode, deepCopy bool) *JSONNode {
293         if that.t != TypeUndefined {
294                 panic(ErrorCopyType)
295         }
296         
297         if other.t == TypeValue {
298                 *that = *other
299         } else if other.t == TypeArray {
300                 if !deepCopy {
301                         *that = *other
302                 } else {
303                         that.Array(len(other.a))
304                         for i := range other.a {
305                                 that.At(i).Copy(other.At(i), deepCopy)
306                         }
307                 }
308         } else if other.t == TypeMap {
309                 that.SetType(other.t)
310                 if !deepCopy {
311                         for val := range other.m {
312                                 that.m[val] = other.m[val]
313                         }
314                 } else {
315                         for val := range other.m {
316                                 that.Map(val).Copy(other.At(val), deepCopy)
317                         }
318                 }
319         }
320         return that
321 }
322
323
324 //Unset Will unset everything in the JSONnode. All the children data will be lost
325 func (that *JSONNode) Unset() {
326         *that = JSONNode{}
327 }
328
329 //DelKey will remove a key in the map.
330 //
331 //return the current JSONNode.
332 func (that *JSONNode) DelKey(key string) *JSONNode {
333         if that.t != TypeMap {
334                 panic(ErrorDeleteKey)
335         }
336         delete(that.m, key)
337         return that
338 }
339
340 //UnmarshalDontExpand set or not if Unmarshall will generate anything in that JSONNode and its children
341 //
342 //val: will change the expanding rules for this node
343 //
344 //- The type wont be change for any type
345 //
346 //- Array wont grow
347 //
348 //- New keys wont be added to Map
349 //
350 //- Values set to nil "*.Val(nil)*" will be turn into the type decide by Json
351 //
352 //- It will respect any current mapping and will return errors if needed
353 //
354 //recurse: if true, it will set all the children of that JSONNode with val
355 func (that *JSONNode) UnmarshalDontExpand(val bool, recurse bool) *JSONNode {
356         that.dontExpand = val
357         if recurse {
358                 switch that.t {
359                 case TypeMap:
360                         for k := range that.m {
361                                 that.m[k].UnmarshalDontExpand(val, recurse)
362                         }
363                 case TypeArray:
364                         for k := range that.a {
365                                 that.a[k].UnmarshalDontExpand(val, recurse)
366                         }
367                 }
368         }
369         return that
370 }
371
372 //MarshalJSON Make JSONNode a Marshaler Interface compatible
373 func (that *JSONNode) MarshalJSON() ([]byte, error) {
374         var ret []byte
375         var err error
376         switch that.t {
377         case TypeMap:
378                 ret, err = json.Marshal(that.m)
379         case TypeArray:
380                 ret, err = json.Marshal(that.a)
381         case TypeValue:
382                 ret, err = json.Marshal(that.v)
383         default:
384                 ret, err = json.Marshal(nil)
385         }
386         if err != nil {
387                 return nil, err
388         }
389         return ret, err
390 }
391
392 func (that *JSONNode) unmarshalMap(data []byte) error {
393         tmp := make(map[string]json.RawMessage)
394         err := json.Unmarshal(data, &tmp)
395         if err != nil {
396                 return err
397         }
398         for k := range tmp {
399                 if _, ok := that.m[k]; ok {
400                         err := json.Unmarshal(tmp[k], that.m[k])
401                         if err != nil {
402                                 return err
403                         }
404                 } else if !that.dontExpand {
405                         err := json.Unmarshal(tmp[k], that.Map(k))
406                         if err != nil {
407                                 return err
408                         }
409                 }
410         }
411         return nil
412 }
413
414 func (that *JSONNode) unmarshalArray(data []byte) error {
415         var tmp []json.RawMessage
416         err := json.Unmarshal(data, &tmp)
417         if err != nil {
418                 return err
419         }
420         for i := len(tmp) - 1; i >= 0; i-- {
421                 if !that.dontExpand || i < len(that.a) {
422                         err := json.Unmarshal(tmp[i], that.At(i))
423                         if err != nil {
424                                 return err
425                         }
426                 }
427         }
428         return nil
429 }
430
431 func (that *JSONNode) unmarshalValue(data []byte) error {
432         if that.v != nil {
433                 return json.Unmarshal(data, that.v)
434         }
435         var tmp interface{}
436         err := json.Unmarshal(data, &tmp)
437         if err != nil {
438                 return err
439         }
440         that.Val(tmp)
441         return nil
442 }
443
444 //UnmarshalJSON Make JSONNode a Unmarshaler Interface compatible
445 func (that *JSONNode) UnmarshalJSON(data []byte) error {
446         if len(data) == 0 {
447                 return nil
448         }
449         if that.dontExpand && that.t == TypeUndefined {
450                 return nil
451         }
452         if that.t == TypeValue {
453                 return that.unmarshalValue(data)
454         }
455         if data[0] == '{' {
456                 if that.t != TypeMap && that.t != TypeUndefined {
457                         return ErrorTypeUnmarshaling
458                 }
459                 return that.unmarshalMap(data)
460         }
461         if data[0] == '[' {
462                 if that.t != TypeArray && that.t != TypeUndefined {
463                         return ErrorTypeUnmarshaling
464                 }
465                 return that.unmarshalArray(data)
466
467         }
468         if that.t == TypeUndefined {
469                 return that.unmarshalValue(data)
470         }
471         return ErrorTypeUnmarshaling
472 }