energy/pkgs/json/array.go
2023-05-31 18:00:34 +08:00

369 lines
9.2 KiB
Go

//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// Go implements JSON serialization and JSON deserialization based on map and slice
// key string, value any
// JSONArray
package json
import (
"encoding/json"
"github.com/energye/energy/v2/consts"
jsoniter "github.com/json-iterator/go"
"reflect"
"strconv"
"strings"
)
// JSONArray
// Manipulate data according to subscript, failure to return the default value of the data type
type JSONArray interface {
BaseJSON
Add(value ...any) // Add data of any type
SetByIndex(index int, value any) // Set any type of data at the specified subscript position
RemoveByIndex(index int) // remove data for index
GetStringByIndex(index int) string // return string data for index
GetIntByIndex(index int) int // return int data for index
GetInt64ByIndex(index int) int64 // return int64 data for index
GetUIntByIndex(index int) uint // return uint data for index
GetUInt64ByIndex(index int) uint64 // return uint64 data for index
GetBytesByIndex(index int) []byte // return []byte data for index
GetFloatByIndex(index int) float64 // return float64 data for index
GetBoolByIndex(index int) bool // return bool data for index
GetArrayByIndex(index int) JSONArray // return JSONArray data for index
GetObjectByIndex(index int) JSONObject // return JSONObject data for index
GetByIndex(index int) JSON // return JSON data for index
}
// NewJSONArray
// byte JSONArray, array & slice convert
// value:
// []byte("[...]")
// []slice
func NewJSONArray(value any) JSONArray {
if value != nil {
// 如果 []byte 就必须是 字节JSONArray
switch value.(type) {
case []byte:
if v := NewJSON(value.([]byte)); v != nil {
return v.JSONArray()
} else {
return nil
}
case string:
if v := NewJSON([]byte(value.(string))); v != nil {
return v.JSONArray()
} else {
return nil
}
}
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
if kind != reflect.Slice && kind != reflect.Array {
return nil
}
//转为[]any类型
if byt, err := jsoniter.Marshal(value); err == nil {
var v []any
if err = jsoniter.Unmarshal(byt, &v); err == nil {
return &JsonData{t: reflect.Slice, v: v, s: len(v)}
}
}
}
return &JsonData{t: reflect.Slice, v: make([]any, 0), s: 0}
}
func (m *JsonData) Add(value ...any) {
if m.IsArray() {
tmp := make([]any, len(value), len(value))
for i, v := range value {
switch v.(type) {
case []byte:
if vv := NewJSON(v.([]byte)); v != nil {
tmp[i] = vv.Data()
} else {
tmp[i] = value
}
case JsonData:
tmp[i] = v.(JsonData)
case *JsonData:
tmp[i] = v.(*JsonData)
case JSON:
tmp[i] = v.(JSON).JsonData()
case JSONObject:
tmp[i] = v.(JSONObject).JsonData()
case JSONArray:
tmp[i] = v.(JSONArray).JsonData()
default:
if isBaseType(v) {
tmp[i] = v
} else {
rv := reflect.ValueOf(v)
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
if kind == reflect.Struct {
// struct -> map
if d, err := jsoniter.Marshal(v); err == nil {
var vv map[string]any
if err = jsoniter.Unmarshal(d, &vv); err == nil {
tmp[i] = vv // json object
}
}
} else if kind == reflect.Slice || kind == reflect.Array {
// slice -> array
if d, err := jsoniter.Marshal(v); err == nil {
var vv []any
if err = jsoniter.Unmarshal(d, &vv); err == nil {
tmp[i] = vv // json array
}
}
} else if kind == reflect.Map {
tmp[i] = v
} else {
tmp[i] = nil
}
}
}
}
m.v = append(m.v.([]any), tmp...)
m.s += len(value)
}
}
func (m *JsonData) SetByIndex(index int, value any) {
if m.IsArray() && index < m.s {
switch value.(type) {
case []byte:
if vv := NewJSON(value.([]byte)); vv != nil {
m.v.([]any)[index] = vv.JsonData()
} else {
m.v.([]any)[index] = value
}
case JsonData:
m.v.([]any)[index] = value.(JsonData)
case *JsonData:
m.v.([]any)[index] = value.(*JsonData)
case JSON:
m.v.([]any)[index] = value.(JSON).JsonData()
case JSONObject:
m.v.([]any)[index] = value.(JSONObject).JsonData()
case JSONArray:
m.v.([]any)[index] = value.(JSONArray).JsonData()
default:
if !isBaseType(value) {
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
if kind == reflect.Struct {
if d, err := jsoniter.Marshal(value); err == nil {
var v map[string]any
if err = jsoniter.Unmarshal(d, &v); err == nil {
value = v // json object
}
}
} else if kind == reflect.Slice || kind == reflect.Array {
if d, err := jsoniter.Marshal(value); err == nil {
var v []any
if err = jsoniter.Unmarshal(d, &v); err == nil {
value = v // json array
}
}
}
}
m.v.([]any)[index] = value
}
}
}
func (m *JsonData) RemoveByIndex(index int) {
if m.IsArray() && index >= 0 && index < m.s {
v := m.v.([]any)
m.v = append(v[:index], v[index+1:]...)
m.s--
}
}
func (m *JsonData) GetStringByIndex(index int) string {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).String()
default:
if r, ok := v.(string); ok {
return r
}
}
}
return ""
}
func (m *JsonData) GetIntByIndex(index int) int {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).Int()
default:
r, _ := toInt(v)
return r
}
}
return 0
}
func (m *JsonData) GetInt64ByIndex(index int) int64 {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).Int64()
default:
r, _ := toInt64(v)
return r
}
}
return 0
}
func (m *JsonData) GetUIntByIndex(index int) uint {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).UInt()
default:
r, _ := toUInt(v)
return r
}
}
return 0
}
func (m *JsonData) GetUInt64ByIndex(index int) uint64 {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).UInt64()
default:
r, _ := toUInt64(v)
return r
}
}
return 0
}
func (m *JsonData) GetBytesByIndex(index int) []byte {
if m.IsArray() && index < m.s {
return toBytes(m.Data())
}
return nil
}
func (m *JsonData) GetFloatByIndex(index int) float64 {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).Float()
default:
r, _ := toFloat64(v)
return r
}
}
return 0
}
func (m *JsonData) GetBoolByIndex(index int) bool {
if m.IsArray() && index < m.s {
v := m.v.([]any)[index]
switch v.(type) {
case *JsonData:
return v.(*JsonData).Bool()
default:
r, _ := toBool(v)
return r
}
}
return false
}
func (m *JsonData) GetArrayByIndex(index int) JSONArray {
return m.GetByIndex(index)
}
func (m *JsonData) GetObjectByIndex(index int) JSONObject {
return m.GetByIndex(index)
}
func (m *JsonData) GetByIndex(index int) JSON {
if m.IsArray() && index < m.s {
value := m.v.([]any)[index]
switch value.(type) {
case JsonData:
v := value.(JsonData)
return &v
case *JsonData:
return value.(*JsonData)
case JSON:
return value.(JSON).JsonData()
case JSONObject:
return value.(JSONObject).JsonData()
case json.Number:
if v, err := value.(json.Number).Int64(); err == nil {
return &JsonData{t: reflect.Int, v: v, s: 8, p: m, pIndex: index}
}
case string:
v := value.(string)
return &JsonData{t: reflect.String, v: v, s: len(v), p: m, pIndex: index}
case int, int8, int16, int32, int64:
v, _ := toInt(value)
return &JsonData{t: reflect.Int, v: v, s: strconv.IntSize, p: m, pIndex: index}
case uint, uint8, uint16, uint32, uint64, uintptr:
v, _ := toUInt(value)
return &JsonData{t: reflect.Uint, v: v, s: strconv.IntSize, p: m, pIndex: index}
case []byte:
if v := m.GetBytesByIndex(index); v != nil {
return &JsonData{t: consts.SLICE_BYTE, v: v, s: len(v), p: m, pIndex: index}
}
case float32, float64:
//不带有 . 转为 int 类型
v, _ := toFloat64(value)
if strings.Index(strconv.FormatFloat(v, 'G', -1, 64), ".") != -1 {
return &JsonData{t: reflect.Float64, v: v, s: 8, p: m, pIndex: index}
} else {
return &JsonData{t: reflect.Int, v: int(v), s: strconv.IntSize, p: m, pIndex: index}
}
case bool:
return &JsonData{t: reflect.Bool, v: value, s: 1, p: m, pIndex: index}
case []any:
if v, ok := value.([]any); ok {
return &JsonData{t: reflect.Slice, v: v, s: len(v), p: m, pIndex: index}
}
case map[string]any:
if v, ok := value.(map[string]any); ok {
return &JsonData{t: reflect.Map, v: v, s: len(v), p: m, pIndex: index}
}
default:
return &JsonData{t: consts.NIL, v: nil, s: 0, p: m, pIndex: index}
}
}
return nil
}