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