413 lines
9.0 KiB
Go
413 lines
9.0 KiB
Go
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
|
|
}
|