diff --git a/gjson.go b/gjson.go index d682d92..bac29a9 100644 --- a/gjson.go +++ b/gjson.go @@ -2,14 +2,9 @@ package gjson import ( - "encoding/base64" "encoding/json" - "errors" - "reflect" "strconv" "strings" - "sync" - "sync/atomic" "time" "unicode/utf16" "unicode/utf8" @@ -2199,145 +2194,6 @@ func GetManyBytes(json []byte, path ...string) []Result { 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) { for ; i < len(data); i++ { switch data[i] { diff --git a/gjson_test.go b/gjson_test.go index 04031ec..7a3255a 100644 --- a/gjson_test.go +++ b/gjson_test.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "math/rand" - "reflect" "strconv" "strings" "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) { t.Helper() _, ok := validpayload([]byte(json), 0)