package jsonvalue import ( "fmt" "reflect" ) // Setter type is for At() only. // // Setter 类型仅用于 At() 函数。 type Setter interface { // At completes the following operation of Set(). It defines position of value // in Set() and return the new value set. // // The usage of At() is perhaps the most important. This function will recursively // search for child value, and set the new value specified by Set() or SetXxx() // series functions. Please unfold and read the following examples, they are important. // // At 完成 Set() 函数的后续操作并设置相应的子成员。其参数指定了应该在哪个位置设置子成员, // 并且返回被设置的子成员对象。 // // 该函数的用法恐怕是 jsonvalue 中最重要的内容了:该函数会按照给定的可变参数递归地一层一层查找 // JSON 值的子成员,并且设置到指定的位置上。设置的逻辑说明起来比较抽象,请打开以下的例子以了解, // 这非常重要。 At(firstParam any, otherParams ...any) (*V, error) } type setter struct { v *V c *V // child err error } // Set starts setting a child JSON value. Any legal JSON value typped parameter // is accepted, such as string, int, float, bool, nil, *jsonvalue.V, or even // a struct or map or slice. // // Please refer to examples of "func (set Setter) At(...)" // // https://godoc.org/github.com/Andrew-M-C/go.jsonvalue/#Set.At // // Set 开始设置一个 JSON 子成员。任何合法的 JSON 类型都可以作为参数, 比如 string, int, // float, bool, nil, *jsonvalue.V 等类型, 甚至也支持结构体、map、切片、数组。 // // 请参见 "func (set Setter) At(...)" 例子. // // https://godoc.org/github.com/Andrew-M-C/go.jsonvalue/#Set.At func (v *V) Set(child any) Setter { var ch *V var err error if child == nil { ch = NewNull() } else if childV, ok := child.(*V); ok { ch = childV } else { ch, err = Import(child) } return &setter{ v: v, c: ch, err: err, } } // SetString is equivalent to Set(jsonvalue.NewString(s)) // // SetString 等效于 Set(jsonvalue.NewString(s)) func (v *V) SetString(s string) Setter { return v.Set(NewString(s)) } // SetBytes is equivalent to Set(NewString(base64.StdEncoding.EncodeToString(b))) // // SetBytes 等效于 Set(NewString(base64.StdEncoding.EncodeToString(b))) func (v *V) SetBytes(b []byte) Setter { s := internal.b64.EncodeToString(b) return v.SetString(s) } // SetBool is equivalent to Set(jsonvalue.NewBool(b)) // // SetBool 等效于 Set(jsonvalue.NewBool(b)) func (v *V) SetBool(b bool) Setter { return v.Set(NewBool(b)) } // SetInt is equivalent to Set(jsonvalue.NewInt(b)) // // SetInt 等效于 Set(jsonvalue.NewInt(b)) func (v *V) SetInt(i int) Setter { return v.Set(NewInt(i)) } // SetInt64 is equivalent to Set(jsonvalue.NewInt64(b)) // // SetInt64 等效于 Set(jsonvalue.NewInt64(b)) func (v *V) SetInt64(i int64) Setter { return v.Set(NewInt64(i)) } // SetInt32 is equivalent to Set(jsonvalue.NewInt32(b)) // // SetInt32 等效于 Set(jsonvalue.NewInt32(b)) func (v *V) SetInt32(i int32) Setter { return v.Set(NewInt32(i)) } // SetUint is equivalent to Set(jsonvalue.NewUint(b)) // // SetUint 等效于 Set(jsonvalue.NewUint(b)) func (v *V) SetUint(u uint) Setter { return v.Set(NewUint(u)) } // SetUint64 is equivalent to Set(jsonvalue.NewUint64(b)) // // SetUint64 is equivalent to Set(jsonvalue.NewUint64(b)) func (v *V) SetUint64(u uint64) Setter { return v.Set(NewUint64(u)) } // SetUint32 is equivalent to Set(jsonvalue.NewUint32(b)) // // SetUint32 等效于 Set(jsonvalue.NewUint32(b)) func (v *V) SetUint32(u uint32) Setter { return v.Set(NewUint32(u)) } // SetFloat64 is equivalent to Set(jsonvalue.NewFloat64(b)) // // SetFloat64 等效于 Set(jsonvalue.NewFloat64(b)) func (v *V) SetFloat64(f float64) Setter { return v.Set(NewFloat64(f)) } // SetFloat32 is equivalent to Set(jsonvalue.NewFloat32(b)) // // SetFloat32 等效于 Set(jsonvalue.NewFloat32(b)) func (v *V) SetFloat32(f float32) Setter { return v.Set(NewFloat32(f)) } // SetNull is equivalent to Set(jsonvalue.NewNull()) // // SetNull 等效于 Set(jsonvalue.NewNull()) func (v *V) SetNull() Setter { return v.Set(NewNull()) } // SetObject is equivalent to Set(jsonvalue.NewObject()) // // SetObject 等效于 Set(jsonvalue.NewObject()) func (v *V) SetObject() Setter { return v.Set(NewObject()) } // SetArray is equivalent to Set(jsonvalue.NewArray()) // // SetArray 等效于 Set(jsonvalue.NewArray()) func (v *V) SetArray() Setter { return v.Set(NewArray()) } func setToObjectChildren(v *V, key string, child *V) { v.children.incrID++ v.children.object[key] = childWithProperty{ id: v.children.incrID, v: child, } addCaselessKey(v, key) } func (s *setter) At(firstParam any, otherParams ...any) (*V, error) { if s.err != nil { return &V{}, s.err } if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok { if len(otherParams) > 0 { return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven } return s.At(p1, p2...) } v := s.v c := s.c if nil == v || v.valueType == NotExist { return &V{}, ErrValueUninitialized } if nil == c || c.valueType == NotExist { return &V{}, ErrValueUninitialized } // this is the last iteration if len(otherParams) == 0 { return s.atLastParam(firstParam) } // this is not the last iterarion if v.valueType == Object { return s.atObject(firstParam, otherParams) } // array type if v.valueType == Array { return s.atArray(firstParam, otherParams) } // illegal type return &V{}, fmt.Errorf("%v type does not supports Set()", v.valueType) } func (s *setter) atLastParam(p any) (*V, error) { v := s.v c := s.c switch v.valueType { default: return &V{}, fmt.Errorf("%v type does not supports Set()", v.valueType) case Object: var k string k, err := anyToString(p) if err != nil { return &V{}, err } setToObjectChildren(v, k, c) return c, nil case Array: pos, err := anyToInt(p) if err != nil { return &V{}, err } err = setAtIndex(v, c, pos) if err != nil { return &V{}, err } return c, nil } } func (s *setter) atObject(firstParam any, otherParams []any) (*V, error) { v := s.v c := s.c k, err := anyToString(firstParam) if err != nil { return &V{}, err } child, exist := getFromObjectChildren(v, false, k) if !exist { if _, err := anyToString(otherParams[0]); err == nil { child = NewObject() } else if i, err := anyToInt(otherParams[0]); err == nil { if i != 0 { return &V{}, ErrOutOfRange } child = NewArray() } else { return &V{}, fmt.Errorf("unexpected type %v for Set()", reflect.TypeOf(otherParams[0])) } } next := &setter{ v: child, c: c, } _, err = next.At(otherParams[0], otherParams[1:]...) if err != nil { return &V{}, err } if !exist { setToObjectChildren(v, k, child) } return c, nil } func (s *setter) atArray(firstParam any, otherParams []any) (*V, error) { v := s.v c := s.c pos, err := anyToInt(firstParam) if err != nil { return &V{}, err } child, ok := childAtIndex(v, pos) isNewChild := false if !ok { isNewChild = true if _, err := anyToString(otherParams[0]); err == nil { child = NewObject() } else if i, err := anyToInt(otherParams[0]); err == nil { if i != 0 { return &V{}, ErrOutOfRange } child = NewArray() } else { return &V{}, fmt.Errorf("unexpected type %v for Set()", reflect.TypeOf(otherParams[0])) } } next := &setter{ v: child, c: c, } _, err = next.At(otherParams[0], otherParams[1:]...) if err != nil { return &V{}, err } // OK to add this object if isNewChild { appendToArr(v, child) } return c, nil } func posAtIndexForSet(v *V, pos int) (newPos int, appendToEnd bool) { if pos == len(v.children.arr) { return pos, true } pos = posAtIndexForRead(v, pos) return pos, false } func posAtIndexForInsertBefore(v *V, pos int) (newPos int) { le := len(v.children.arr) if le == 0 { return -1 } if pos == 0 { return 0 } if pos < 0 { pos += le if pos < 0 { return -1 } return pos } if pos >= le { return -1 } return pos } func posAtIndexForInsertAfter(v *V, pos int) (newPos int, appendToEnd bool) { le := len(v.children.arr) if le == 0 { return -1, false } if pos == -1 { return le, true } if pos < 0 { pos += le if pos < 0 { return -1, false } return pos + 1, false } if pos >= le { return -1, false } return pos + 1, false } func posAtIndexForRead(v *V, pos int) int { le := len(v.children.arr) if le == 0 { return -1 } if pos < 0 { pos += le if pos < 0 { return -1 } return pos } if pos >= le { return -1 } return pos } func childAtIndex(v *V, pos int) (*V, bool) { // if nil returned, means that just push pos = posAtIndexForRead(v, pos) if pos < 0 { return &V{}, false } return v.children.arr[pos], true } func setAtIndex(v *V, child *V, pos int) error { pos, appendToEnd := posAtIndexForSet(v, pos) if pos < 0 { return ErrOutOfRange } if appendToEnd { v.children.arr = append(v.children.arr, child) } else { v.children.arr[pos] = child } return nil }