package gson import ( "encoding/json" "io" "reflect" "sync" ) // New JSON from []byte, [io.Reader], or raw value. func New(v interface{}) JSON { return JSON{&sync.Mutex{}, &v} } // NewFrom json encoded string func NewFrom(s string) JSON { return New([]byte(s)) } // UnmarshalJSON interface func (j *JSON) UnmarshalJSON(b []byte) error { *j = New(b) return nil } // Val of the underlying json value. // The first time it's called, it will try to parse the underlying data. func (j JSON) Val() interface{} { if j.value == nil { return nil } j.lock.Lock() defer j.lock.Unlock() for { val, ok := (*j.value).(JSON) if ok { *j.value = *val.value } else { break } } var val interface{} switch v := (*j.value).(type) { case []byte: _ = json.Unmarshal(v, &val) *j.value = val case io.Reader: _ = json.NewDecoder(v).Decode(&val) *j.value = val } return *j.value } // Set by json path. It's a shortcut for Sets. func (j *JSON) Set(path string, val interface{}) *JSON { return j.Sets(val, Path(path)...) } var _map map[string]interface{} var interfaceType = reflect.TypeOf(_map).Elem() // Sets element by path sections. If a section is not string or int, it will be ignored. func (j *JSON) Sets(target interface{}, sections ...interface{}) *JSON { if j.value == nil { *j = New(nil) } last := len(sections) - 1 val := reflect.ValueOf(j.Val()) override := func(v reflect.Value) { *j.value = v.Interface() } if last == -1 { *j.value = target return j } for i, s := range sections { sect := reflect.ValueOf(s) if val.Kind() == reflect.Interface { val = val.Elem() } switch sect.Kind() { case reflect.Int: k := int(sect.Int()) if val.Kind() != reflect.Slice || val.Len() <= k { nArr := reflect.ValueOf(make([]interface{}, k+1)) if val.Kind() == reflect.Slice { reflect.Copy(nArr, val) } val = nArr override(val) } if i == last { val.Index(k).Set(reflect.ValueOf(target)) return j } prev := val val = val.Index(k) override = func(v reflect.Value) { prev.Index(k).Set(v) } default: targetVal := reflect.ValueOf(target) if val.Kind() != reflect.Map { val = reflect.MakeMap(reflect.MapOf(sect.Type(), interfaceType)) override(val) } if i == last { val.SetMapIndex(sect, targetVal) } prev := val val = val.MapIndex(sect) override = func(v reflect.Value) { prev.SetMapIndex(sect, v) } } } return j } // Del deletes the element at the path. func (j *JSON) Del(path string) *JSON { j.Dels(Path(path)...) return j } // Dels deletes the element at the path sections. // Return true if it's deleted. func (j *JSON) Dels(sections ...interface{}) bool { l := len(sections) if l == 0 { j.value = nil return true } last := sections[l-1] parent, has := j.Gets(sections[:l-1]...) if !has { return false } parentVal := reflect.ValueOf(parent.Val()) lastVal := reflect.ValueOf(last) switch k := last.(type) { case int: pl := parentVal.Len() if parentVal.Kind() != reflect.Slice || k < 0 || k >= pl { return false } j.Sets(reflect.AppendSlice( parentVal.Slice(0, k), parentVal.Slice(k+1, pl), ).Interface(), sections[:l-1]...) default: if parentVal.Kind() != reflect.Map || !lastVal.Type().AssignableTo(parentVal.Type().Key()) { return false } parentVal.SetMapIndex(lastVal, reflect.Value{}) } return true }