package jsoniter import ( "fmt" "reflect" ) type Any struct { Val interface{} Error error } func (any *Any) GetObject(keys ...interface{}) interface{} { ret, err := getPath(any.Val, keys...) if err != nil { any.Error = err return ""; } return ret } func (any *Any) GetString(keys ...interface{}) string { ret, err := getPath(any.Val, keys...) if err != nil { any.Error = err return ""; } typedRet, ok := ret.(string) if !ok { any.Error = fmt.Errorf("%v is not string", ret); return ""; } return typedRet } func (any *Any) GetUint8(keys ...interface{}) uint8 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return uint8(ret) } func (any *Any) GetInt8(keys ...interface{}) int8 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return int8(ret) } func (any *Any) GetUint16(keys ...interface{}) uint16 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return uint16(ret) } func (any *Any) GetInt16(keys ...interface{}) int16 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return int16(ret) } func (any *Any) GetUint32(keys ...interface{}) uint32 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return uint32(ret) } func (any *Any) GetInt32(keys ...interface{}) int32 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return int32(ret) } func (any *Any) GetUint64(keys ...interface{}) uint64 { ret, err := getPathAsUint64(any.Val, keys...) if err != nil { any.Error = err return 0; } return uint64(ret) } func (any *Any) GetInt64(keys ...interface{}) int64 { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return int64(ret) } func (any *Any) GetInt(keys ...interface{}) int { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return int(ret) } func (any *Any) GetUint(keys ...interface{}) uint { ret, err := getPathAsInt64(any.Val, keys...) if err != nil { any.Error = err return 0; } return uint(ret) } func (any *Any) GetFloat32(keys ...interface{}) float32 { ret, err := getPathAsFloat64(any.Val, keys...) if err != nil { any.Error = err return 0; } return float32(ret) } func (any *Any) GetFloat64(keys ...interface{}) float64 { ret, err := getPathAsFloat64(any.Val, keys...) if err != nil { any.Error = err return 0; } return ret } func (any *Any) GetBool(keys ...interface{}) bool { ret, err := getPath(any.Val, keys...) if err != nil { any.Error = err return false; } typedRet, ok := ret.(bool) if !ok { any.Error = fmt.Errorf("%v is not bool", ret) return false; } return typedRet } func (any *Any) IsNull(keys ...interface{}) bool { ret, err := getPath(any.Val, keys...) if err != nil { any.Error = err return false; } return reflect.ValueOf(ret).IsNil() } func getPathAsInt64(val interface{}, keys ...interface{}) (int64, error) { ret, err := getPath(val, keys...) if err != nil { return 0, err } switch ret := ret.(type) { case uint8: return int64(ret), nil; case int8: return int64(ret), nil; case uint16: return int64(ret), nil; case int16: return int64(ret), nil; case uint32: return int64(ret), nil; case int32: return int64(ret), nil; case uint64: return int64(ret), nil; case int64: return int64(ret), nil; case int: return int64(ret), nil; case uint: return int64(ret), nil; case float32: return int64(ret), nil; case float64: return int64(ret), nil; default: return 0, fmt.Errorf("%v is not number", ret) } } func getPathAsUint64(val interface{}, keys ...interface{}) (uint64, error) { ret, err := getPath(val, keys...) if err != nil { return 0, err } switch ret := ret.(type) { case uint8: return uint64(ret), nil; case int8: return uint64(ret), nil; case uint16: return uint64(ret), nil; case int16: return uint64(ret), nil; case uint32: return uint64(ret), nil; case int32: return uint64(ret), nil; case uint64: return uint64(ret), nil; case int64: return uint64(ret), nil; case int: return uint64(ret), nil; case uint: return uint64(ret), nil; case float32: return uint64(ret), nil; case float64: return uint64(ret), nil; default: return 0, fmt.Errorf("%v is not number", ret) } } func getPathAsFloat64(val interface{}, keys ...interface{}) (float64, error) { ret, err := getPath(val, keys...) if err != nil { return 0, err } switch ret := ret.(type) { case uint8: return float64(ret), nil; case int8: return float64(ret), nil; case uint16: return float64(ret), nil; case int16: return float64(ret), nil; case uint32: return float64(ret), nil; case int32: return float64(ret), nil; case uint64: return float64(ret), nil; case int64: return float64(ret), nil; case int: return float64(ret), nil; case uint: return float64(ret), nil; case float32: return float64(ret), nil; case float64: return float64(ret), nil; default: return 0, fmt.Errorf("%v is not number", ret) } } func getPath(val interface{}, keys ...interface{}) (interface{}, error) { if (len(keys) == 0) { return val, nil; } switch key := keys[0].(type) { case string: nextVal, err := getFromMap(val, key) if err != nil { return nil, err } nextKeys := make([]interface{}, len(keys) - 1) copy(nextKeys, keys[1:]) return getPath(nextVal, nextKeys...) case int: nextVal, err := getFromArray(val, key) if err != nil { return nil, err } nextKeys := make([]interface{}, len(keys) - 1) copy(nextKeys, keys[1:]) return getPath(nextVal, nextKeys...) default: return nil, fmt.Errorf("%v is not string or int", keys[0]); } return getPath(val, keys); } func getFromMap(val interface{}, key string) (interface{}, error) { mapVal, ok := val.(map[string]interface{}) if !ok { return nil, fmt.Errorf("%v is not map[string]interface{}", val) } ret, found := mapVal[key] if !found { return nil, fmt.Errorf("%v not found in %v", key, mapVal) } return ret, nil } func getFromArray(val interface{}, key int) (interface{}, error) { arrayVal, ok := val.([]interface{}) if !ok { return nil, fmt.Errorf("%v is not []interface{}", val) } if key >= len(arrayVal) { return nil, fmt.Errorf("%v exceed %v", key, arrayVal) } if key < 0 { return nil, fmt.Errorf("%v exceed %v", key, arrayVal) } return arrayVal[key], nil }