mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-08 21:38:15 +02:00
f5e6f53d75
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
176 lines
3.4 KiB
Go
176 lines
3.4 KiB
Go
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
|
|
}
|