forked from mirror/gjson
Removed unmarshalling
This commit is contained in:
parent
12826915de
commit
d10932a0d0
144
gjson.go
144
gjson.go
|
@ -2,14 +2,9 @@
|
||||||
package gjson
|
package gjson
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -2199,145 +2194,6 @@ func GetManyBytes(json []byte, path ...string) []Result {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
var fieldsmu sync.RWMutex
|
|
||||||
var fields = make(map[string]map[string]int)
|
|
||||||
|
|
||||||
func assign(jsval Result, goval reflect.Value) {
|
|
||||||
if jsval.Type == Null {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch goval.Kind() {
|
|
||||||
default:
|
|
||||||
case reflect.Ptr:
|
|
||||||
if !goval.IsNil() {
|
|
||||||
newval := reflect.New(goval.Elem().Type())
|
|
||||||
assign(jsval, newval.Elem())
|
|
||||||
goval.Elem().Set(newval.Elem())
|
|
||||||
} else {
|
|
||||||
newval := reflect.New(goval.Type().Elem())
|
|
||||||
assign(jsval, newval.Elem())
|
|
||||||
goval.Set(newval)
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
fieldsmu.RLock()
|
|
||||||
sf := fields[goval.Type().String()]
|
|
||||||
fieldsmu.RUnlock()
|
|
||||||
if sf == nil {
|
|
||||||
fieldsmu.Lock()
|
|
||||||
sf = make(map[string]int)
|
|
||||||
for i := 0; i < goval.Type().NumField(); i++ {
|
|
||||||
f := goval.Type().Field(i)
|
|
||||||
tag := strings.Split(f.Tag.Get("json"), ",")[0]
|
|
||||||
if tag != "-" {
|
|
||||||
if tag != "" {
|
|
||||||
sf[tag] = i
|
|
||||||
sf[f.Name] = i
|
|
||||||
} else {
|
|
||||||
sf[f.Name] = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fields[goval.Type().String()] = sf
|
|
||||||
fieldsmu.Unlock()
|
|
||||||
}
|
|
||||||
jsval.ForEach(func(key, value Result) bool {
|
|
||||||
if idx, ok := sf[key.Str]; ok {
|
|
||||||
f := goval.Field(idx)
|
|
||||||
if f.CanSet() {
|
|
||||||
assign(value, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
case reflect.Slice:
|
|
||||||
if goval.Type().Elem().Kind() == reflect.Uint8 &&
|
|
||||||
jsval.Type == String {
|
|
||||||
data, _ := base64.StdEncoding.DecodeString(jsval.String())
|
|
||||||
goval.Set(reflect.ValueOf(data))
|
|
||||||
} else {
|
|
||||||
jsvals := jsval.Array()
|
|
||||||
slice := reflect.MakeSlice(goval.Type(), len(jsvals), len(jsvals))
|
|
||||||
for i := 0; i < len(jsvals); i++ {
|
|
||||||
assign(jsvals[i], slice.Index(i))
|
|
||||||
}
|
|
||||||
goval.Set(slice)
|
|
||||||
}
|
|
||||||
case reflect.Array:
|
|
||||||
i, n := 0, goval.Len()
|
|
||||||
jsval.ForEach(func(_, value Result) bool {
|
|
||||||
if i == n {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
assign(value, goval.Index(i))
|
|
||||||
i++
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
case reflect.Map:
|
|
||||||
if goval.Type().Key().Kind() == reflect.String &&
|
|
||||||
goval.Type().Elem().Kind() == reflect.Interface {
|
|
||||||
goval.Set(reflect.ValueOf(jsval.Value()))
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
goval.Set(reflect.ValueOf(jsval.Value()))
|
|
||||||
case reflect.Bool:
|
|
||||||
goval.SetBool(jsval.Bool())
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
goval.SetFloat(jsval.Float())
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
||||||
reflect.Int64:
|
|
||||||
goval.SetInt(jsval.Int())
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
|
||||||
reflect.Uint64:
|
|
||||||
goval.SetUint(jsval.Uint())
|
|
||||||
case reflect.String:
|
|
||||||
goval.SetString(jsval.String())
|
|
||||||
}
|
|
||||||
if len(goval.Type().PkgPath()) > 0 {
|
|
||||||
v := goval.Addr()
|
|
||||||
if v.Type().NumMethod() > 0 {
|
|
||||||
if u, ok := v.Interface().(json.Unmarshaler); ok {
|
|
||||||
u.UnmarshalJSON([]byte(jsval.Raw))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var validate uintptr = 1
|
|
||||||
|
|
||||||
// UnmarshalValidationEnabled provides the option to disable JSON validation
|
|
||||||
// during the Unmarshal routine. Validation is enabled by default.
|
|
||||||
//
|
|
||||||
// Deprecated: Use encoder/json.Unmarshal instead
|
|
||||||
func UnmarshalValidationEnabled(enabled bool) {
|
|
||||||
if enabled {
|
|
||||||
atomic.StoreUintptr(&validate, 1)
|
|
||||||
} else {
|
|
||||||
atomic.StoreUintptr(&validate, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal loads the JSON data into the value pointed to by v.
|
|
||||||
//
|
|
||||||
// This function works almost identically to json.Unmarshal except that
|
|
||||||
// gjson.Unmarshal will automatically attempt to convert JSON values to any Go
|
|
||||||
// type. For example, the JSON string "100" or the JSON number 100 can be
|
|
||||||
// equally assigned to Go string, int, byte, uint64, etc. This rule applies to
|
|
||||||
// all types.
|
|
||||||
//
|
|
||||||
// Deprecated: Use encoder/json.Unmarshal instead
|
|
||||||
func Unmarshal(data []byte, v interface{}) error {
|
|
||||||
if atomic.LoadUintptr(&validate) == 1 {
|
|
||||||
_, ok := validpayload(data, 0)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("invalid json")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v := reflect.ValueOf(v); v.Kind() == reflect.Ptr {
|
|
||||||
assign(ParseBytes(data), v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validpayload(data []byte, i int) (outi int, ok bool) {
|
func validpayload(data []byte, i int) (outi int, ok bool) {
|
||||||
for ; i < len(data); i++ {
|
for ; i < len(data); i++ {
|
||||||
switch data[i] {
|
switch data[i] {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -996,26 +995,6 @@ var complicatedJSON = `
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func TestUnmarshal(t *testing.T) {
|
|
||||||
var s1 ComplicatedType
|
|
||||||
var s2 ComplicatedType
|
|
||||||
if err := json.Unmarshal([]byte(complicatedJSON), &s1); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := Unmarshal([]byte(complicatedJSON), &s2); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(&s1, &s2) {
|
|
||||||
t.Fatal("not equal")
|
|
||||||
}
|
|
||||||
var str string
|
|
||||||
err := json.Unmarshal([]byte(Get(complicatedJSON, "LeftOut").Raw), &str)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
assert(t, str == Get(complicatedJSON, "LeftOut").String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func testvalid(t *testing.T, json string, expect bool) {
|
func testvalid(t *testing.T, json string, expect bool) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
_, ok := validpayload([]byte(json), 0)
|
_, ok := validpayload([]byte(json), 0)
|
||||||
|
|
Loading…
Reference in New Issue