// Package jsonvalue is for JSON parsing and setting. It is used in situations those // Go structures cannot achieve, or "map[string]any" could not do properly. // // As a quick start: // // v := jsonvalue.NewObject() // v.SetString("Hello, JSON").At("someObject", "someObject", "someObject", "message") // automatically create sub objects // fmt.Println(v.MustMarshalString()) // marshal to string type. Use MustMarshal if you want []byte instead. // // Output: // // {"someObject":{"someObject":{"someObject":{"message":"Hello, JSON!"}}} // // If you want to parse raw JSON data, use Unmarshal() // // raw := []byte(`{"message":"hello, world"}`) // v, err := jsonvalue.Unmarshal(raw) // s, _ := v.GetString("message") // fmt.Println(s) // // Output: // // hello, world // // jsonvalue 包用于 JSON 的解析(反序列化)和编码(序列化)。通常情况下我们用 struct 来处理 // 结构化的 JSON,但是有时候使用 struct 不方便或者是功能不足的时候,go 一般而言使用的是 // "map[string]any",但是后者也有很多不方便的地方。本包即是用于替代这些不方便的情况的。 // // 快速上手: // // v := jsonvalue.NewObject() // v.SetString("Hello, JSON").At("someObject", "someObject", "someObject", "message") // 自动创建子成员 // fmt.Println(v.MustMarshalString()) // 序列化为 string 类型,如果你要 []byte 类型,则使用 MustMarshal 函数。 // // 输出: // // {"someObject":{"someObject":{"someObject":{"message":"Hello, JSON!"}}} // // 如果要反序列化原始的 JSON 文本,则使用 Unmarshal(): // // raw := []byte(`{"message":"hello, world"}`) // v, err := jsonvalue.Unmarshal(raw) // s, _ := v.GetString("message") // fmt.Println(s) // // 输出: // // hello, world package jsonvalue import ( "bytes" "strconv" "strings" "github.com/Andrew-M-C/go.jsonvalue/internal/unsafe" ) // ValueType identifying JSON value type type ValueType int const ( // NotExist type tells that this JSON value is not exist or legal NotExist ValueType = iota // String JSON string type String // Number JSON number type Number // Object JSON object type Object // Array JSON array type Array // Boolean JSON boolean type Boolean // Null JSON null type Null // Unknown unknown JSON type Unknown ) var typeStr = [Unknown + 1]string{ "illegal", "string", "number", "object", "array", "boolean", "null", "unknown", } // String show the type name of JSON func (t ValueType) String() string { if t > Unknown { t = NotExist } else if t < 0 { t = NotExist } return typeStr[int(t)] } // ValueType returns the type of this JSON value. func (v *V) ValueType() ValueType { return v.valueType } // V is the main type of jsonvalue, representing a JSON value. // // V 是 jsonvalue 的主类型,表示一个 JSON 值。 type V struct { valueType ValueType srcByte []byte num num valueStr string valueBool bool children children } type num struct { negative bool floated bool i64 int64 u64 uint64 f64 float64 } type childWithProperty struct { id uint32 v *V } type children struct { incrID uint32 arr []*V object map[string]childWithProperty // As official json package supports caseless key accessing, I decide to do it as well lowerCaseKeys map[string]map[string]struct{} } func (c *children) deepCopy() children { res := children{ incrID: c.incrID, } // if length or arr > 0, this must be an array type if len(c.arr) > 0 { for _, v := range c.arr { res.arr = append(res.arr, v.deepCopy()) } return res } // if this is an object? if c.object != nil { res.object = make(map[string]childWithProperty, len(c.object)) for key, item := range c.object { res.object[key] = childWithProperty{ id: item.id, v: item.v.deepCopy(), } } } // no need to copy lowerCaseKeys because it could be rebuild after calling // Caseless() next time return res } func addCaselessKey(v *V, k string) { if v.children.lowerCaseKeys == nil { return } lowerK := strings.ToLower(k) keys, exist := v.children.lowerCaseKeys[lowerK] if !exist { keys = make(map[string]struct{}) v.children.lowerCaseKeys[lowerK] = keys } keys[k] = struct{}{} } func delCaselessKey(v *V, k string) { if v.children.lowerCaseKeys == nil { return } lowerK := strings.ToLower(k) keys, exist := v.children.lowerCaseKeys[lowerK] if !exist { return } delete(keys, k) if len(keys) == 0 { delete(v.children.lowerCaseKeys, lowerK) } } // MustUnmarshalString just like UnmarshalString(). If error occurs, a JSON value // with "NotExist" type would be returned, which could do nothing and return nothing // in later use. It is useful to shorten codes. // // MustUnmarshalString 的逻辑与 UnmarshalString() 相同,不过如果错误的话,会返回一个类型未 // "NotExist" 的 JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。 // 但起码不会导致程序 panic,便于使用短代码实现一些默认逻辑。 func MustUnmarshalString(s string) *V { v, _ := UnmarshalString(s) return v } // UnmarshalString is equivalent to Unmarshal([]byte(b)), but more efficient. // // UnmarshalString 等效于 Unmarshal([]byte(b)),但效率更高。 func UnmarshalString(s string) (*V, error) { // reference: https://stackoverflow.com/questions/41591097/slice-bounds-out-of-range-when-using-unsafe-pointer // sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) // bh := reflect.SliceHeader{ // Data: sh.Data, // Len: sh.Len, // Cap: sh.Len, // } // b := *(*[]byte)(unsafe.Pointer(&bh)) b := []byte(s) return UnmarshalNoCopy(b) } // MustUnmarshal just like Unmarshal(). If error occurs, a JSON value with "NotExist" // type would be returned, which could do nothing and return nothing in later use. It // is useful to shorten codes. // // MustUnmarshal 的逻辑与 Unmarshal() 相同,不过如果错误的话,会返回一个类型未 "NotExist" 的 // JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。但起码不会导致程序 // panic,便于使用短代码实现一些默认逻辑。 func MustUnmarshal(b []byte) *V { v, _ := Unmarshal(b) return v } // Unmarshal parse raw bytes(encoded in UTF-8 or pure AscII) and returns a *V instance. // // Unmarshal 解析原始的字节类型数据(以 UTF-8 或纯 AscII 编码),并返回一个 *V 对象。 func Unmarshal(b []byte) (ret *V, err error) { le := len(b) if le == 0 { return nil, ErrNilParameter } trueB := make([]byte, len(b)) copy(trueB, b) it := iter(trueB) p := newPool(len(b)) ret, err = unmarshalWithIter(p, it, 0) p.release() return } // MustUnmarshalNoCopy just like UnmarshalNoCopy(). If error occurs, a JSON value // with "NotExist" type would be returned, which could do nothing and return nothing // in later use. It is useful to shorten codes. // // MustUnmarshalNoCopy 的逻辑与 UnmarshalNoCopy() 相同,不过如果错误的话,会返回一个类型未 // "NotExist" 的 JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。 // 但起码不会导致程序 panic,便于使用短代码实现一些默认逻辑。 func MustUnmarshalNoCopy(b []byte) *V { v, _ := UnmarshalNoCopy(b) return v } // UnmarshalNoCopy is same as Unmarshal, but it does not copy another []byte instance // for saving CPU time. But pay attention that the input []byte may be used as buffer // by jsonvalue and mey be modified. // // UnmarshalNoCopy 与 Unmarshal 相同,但是这个函数在解析过程中不会重新复制一个 []byte,对于大 // json 的解析而言能够大大节省时间。但请注意传入的 []byte 变量可能会被 jsonvalue 用作缓冲区,并进行修改 func UnmarshalNoCopy(b []byte) (ret *V, err error) { le := len(b) if le == 0 { return &V{}, ErrNilParameter } p := newPool(len(b)) ret, err = unmarshalWithIter(p, iter(b), 0) p.release() return } // ==== type access ==== // IsObject tells whether value is an object // // IsObject 判断当前值是不是一个对象类型 func (v *V) IsObject() bool { return v.valueType == Object } // IsArray tells whether value is an array // // IsArray 判断当前值是不是一个数组类型 func (v *V) IsArray() bool { return v.valueType == Array } // IsString tells whether value is a string // // IsString 判断当前值是不是一个字符串类型 func (v *V) IsString() bool { return v.valueType == String } // IsNumber tells whether value is a number // // IsNumber 判断当前值是不是一个数字类型 func (v *V) IsNumber() bool { return v.valueType == Number } // IsFloat tells whether value is a float point number. If there is no decimal point // in original text, it returns false while IsNumber returns true. // // IsFloat 判断当前值是不是一个浮点数类型。如果给定的数不包含小数点,那么即便是数字类型,该函数也会返回 false. func (v *V) IsFloat() bool { if v.valueType != Number { return false } return v.num.floated } // IsInteger tells whether value is a fix point integer // // IsNumber 判断当前值是不是一个定点数整型 func (v *V) IsInteger() bool { if v.valueType != Number { return false } return !(v.num.floated) } // IsNegative tells whether value is a negative number // // IsNegative 判断当前值是不是一个负数 func (v *V) IsNegative() bool { if v.valueType != Number { return false } return v.num.negative } // IsPositive tells whether value is a positive number // // IsPositive 判断当前值是不是一个正数 func (v *V) IsPositive() bool { if v.valueType != Number { return false } return !(v.num.negative) } // GreaterThanInt64Max return true when ALL conditions below are met: // 1. It is a number value. // 2. It is a positive integer. // 3. Its value is greater than 0x7fffffffffffffff. // // GreaterThanInt64Max 判断当前值是否超出 int64 可表示的范围。当以下条件均成立时,返回 true, // 否则返回 false: // 1. 是一个数字类型值. // 2. 是一个正整型数字. // 3. 该正整数的值大于 0x7fffffffffffffff. func (v *V) GreaterThanInt64Max() bool { if v.valueType != Number { return false } if v.num.negative { return false } return v.num.u64 > 0x7fffffffffffffff } // IsBoolean tells whether value is a boolean // // IsBoolean 判断当前值是不是一个布尔类型 func (v *V) IsBoolean() bool { return v.valueType == Boolean } // IsNull tells whether value is a null // // IsBoolean 判断当前值是不是一个空类型 func (v *V) IsNull() bool { return v.valueType == Null } // Bool returns represented bool value. If value is not boolean, returns false. // // Bool 返回布尔类型值。如果当前值不是布尔类型,则判断是否为 string,不是 string 返回 false; // 是 string 的话则返回字面值是否等于 true func (v *V) Bool() bool { if v.valueType == Boolean { return v.valueBool } b, _ := getBoolAndErrorFromValue(v) return b.valueBool } // Int returns represented int value. If value is not a number, returns zero. // // Int 返回 int 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Int() int { if v.valueType != Number { return getNumberFromNotNumberValue(v).Int() } return int(v.num.i64) } // Uint returns represented uint value. If value is not a number, returns zero. // // Uint 返回 uint 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Uint() uint { if v.valueType != Number { return getNumberFromNotNumberValue(v).Uint() } return uint(v.num.u64) } // Int64 returns represented int64 value. If value is not a number, returns zero. // // Int64 返回 int64 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Int64() int64 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Int64() } return int64(v.num.i64) } // Uint64 returns represented uint64 value. If value is not a number, returns zero. // // Uint64 返回 uint64 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Uint64() uint64 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Uint64() } return uint64(v.num.u64) } // Int32 returns represented int32 value. If value is not a number, returns zero. // // Int32 返回 int32 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Int32() int32 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Int32() } return int32(v.num.i64) } // Uint32 returns represented uint32 value. If value is not a number, returns zero. // // Uint32 返回 uint32 类型值。如果当前值不是数字类型,则返回 0。 func (v *V) Uint32() uint32 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Uint32() } return uint32(v.num.u64) } // Float64 returns represented float64 value. If value is not a number, returns zero. // // Float64 返回 float64 类型值。如果当前值不是数字类型,则返回 0.0。 func (v *V) Float64() float64 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Float64() } return v.num.f64 } // Float32 returns represented float32 value. If value is not a number, returns zero. // // Float32 返回 float32 类型值。如果当前值不是数字类型,则返回 0.0。 func (v *V) Float32() float32 { if v.valueType != Number { return getNumberFromNotNumberValue(v).Float32() } return float32(v.num.f64) } // Bytes returns represented binary data which is encoded as Base64 string. []byte{} // would be returned if value is // not a string type or base64 decode failed. // // Bytes 返回以 Base64 编码在 string 类型中的二进制数据。如果当前值不是字符串类型,或者是 base64 // 编码失败,则返回 []byte{}。 func (v *V) Bytes() []byte { if v.valueType != String { return []byte{} } b, err := internal.b64.DecodeString(v.valueStr) if err != nil { return []byte{} } return b } func (v *V) deepCopy() *V { if v == nil { return &V{} } switch v.valueType { default: // fallthrough // case NotExist, Unknown: return &V{} case String: return NewString(v.String()) case Number: res := new(globalPool{}, Number) res.num = v.num res.srcByte = v.srcByte return res case Object: res := new(globalPool{}, Object) res.children = v.children.deepCopy() return res case Array: res := new(globalPool{}, Array) res.children = v.children.deepCopy() return res case Boolean: return NewBool(v.Bool()) case Null: return NewNull() } } type deepCopier interface { deepCopy() *V } // String returns represented string value or the description for the jsonvalue.V // instance if it is not a string. // // String 返回 string 类型值。如果当前值不是字符串类型,则返回当前 *V 类型的描述说明。 func (v *V) String() string { if v == nil { return "nil" } switch v.valueType { default: return "" case Null: return "null" case Number: if len(v.srcByte) > 0 { return unsafe.BtoS(v.srcByte) } return strconv.FormatFloat(v.num.f64, 'g', -1, 64) case String: return v.valueStr case Boolean: return formatBool(v.valueBool) case Object: return packObjChildren(v) case Array: return packArrChildren(v) } } func packObjChildren(v *V) string { buf := bytes.Buffer{} bufObjChildren(v, &buf) return buf.String() } func bufObjChildren(v *V, buf *bytes.Buffer) { buf.WriteByte('{') i := 0 for k, v := range v.children.object { if i > 0 { buf.WriteString(", ") } buf.WriteString(k) buf.WriteString(": ") buf.WriteString(v.v.String()) i++ } buf.WriteByte('}') } func packArrChildren(v *V) string { buf := bytes.Buffer{} bufArrChildren(v, &buf) return buf.String() } func bufArrChildren(v *V, buf *bytes.Buffer) { buf.WriteByte('[') v.RangeArray(func(i int, v *V) bool { if i > 0 { buf.WriteString(", ") } buf.WriteString(v.String()) return true }) buf.WriteByte(']') }