256 lines
6.3 KiB
Go
256 lines
6.3 KiB
Go
package gjson
|
||
|
||
import (
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
// GetProperty 获取属性值
|
||
func GetProperty(obj JSONBaseObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) {
|
||
// 首先尝试将obj转换为其实际类型
|
||
switch v := obj.(type) {
|
||
case *JSONObject:
|
||
return getFromJSONObject(v, propertyPath, defaultValue)
|
||
case *JSONArray:
|
||
return getFromJSONArray(v, propertyPath, defaultValue)
|
||
default:
|
||
// 如果是基础类型,直接返回默认值
|
||
return defaultValue, nil
|
||
}
|
||
}
|
||
|
||
// SetProperty 设置属性值
|
||
func SetProperty(obj JSONBaseObject, propertyPath string, value JSONBaseObject) error {
|
||
switch v := obj.(type) {
|
||
case *JSONObject:
|
||
return setInJSONObject(v, propertyPath, value)
|
||
case *JSONArray:
|
||
return setInJSONArray(v, propertyPath, value)
|
||
default:
|
||
// 不支持对基本值类型设置属性
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// 从JSONObject中获取属性
|
||
func getFromJSONObject(obj *JSONObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) {
|
||
pathParts := strings.Split(propertyPath, ".")
|
||
currentData := obj.data
|
||
|
||
// 遍历路径直到到达最终部分
|
||
for i := 0; i < len(pathParts); i++ {
|
||
key := pathParts[i]
|
||
value, exists := currentData[key]
|
||
if !exists {
|
||
return defaultValue, nil
|
||
}
|
||
|
||
// 如果这是最后一个路径部分,返回值
|
||
if i == len(pathParts)-1 {
|
||
return convertToJSONBaseObject(value), nil
|
||
}
|
||
|
||
// 否则继续深入嵌套对象
|
||
if nextMap, ok := value.(map[string]interface{}); ok {
|
||
currentData = nextMap
|
||
} else {
|
||
// 如果路径还没结束但无法继续深入,返回默认值
|
||
return defaultValue, nil
|
||
}
|
||
}
|
||
|
||
return defaultValue, nil
|
||
}
|
||
|
||
// 从JSONArray中获取属性
|
||
func getFromJSONArray(arr *JSONArray, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) {
|
||
// 解析路径,支持数组索引
|
||
parts := strings.Split(propertyPath, ".")
|
||
|
||
// 第一部分应该是数组索引
|
||
indexStr := parts[0]
|
||
index, err := strconv.Atoi(indexStr)
|
||
if err != nil {
|
||
return defaultValue, err
|
||
}
|
||
|
||
// 获取数组元素
|
||
element, exists := arr.Get(index)
|
||
if !exists {
|
||
return defaultValue, nil
|
||
}
|
||
|
||
// 如果有后续路径部分,说明要访问嵌套对象
|
||
if len(parts) > 1 {
|
||
remainingPath := strings.Join(parts[1:], ".")
|
||
|
||
// 检查元素类型并递归查找
|
||
switch elem := element.(type) {
|
||
case map[string]interface{}:
|
||
// 创建临时JSONObject用于查找
|
||
tempObj := &JSONObject{data: elem}
|
||
return getFromJSONObject(tempObj, remainingPath, defaultValue)
|
||
case []interface{}:
|
||
// 创建临时JSONArray用于查找
|
||
tempArr := &JSONArray{data: elem}
|
||
return getFromJSONArray(tempArr, remainingPath, defaultValue)
|
||
default:
|
||
// 其他类型无法继续访问属性
|
||
return defaultValue, nil
|
||
}
|
||
}
|
||
|
||
// 如果没有更多路径部分,直接返回元素
|
||
return convertToJSONBaseObject(element), nil
|
||
}
|
||
|
||
// 在JSONObject中设置属性
|
||
func setInJSONObject(obj *JSONObject, propertyPath string, value JSONBaseObject) error {
|
||
pathParts := strings.Split(propertyPath, ".")
|
||
currentData := obj.data
|
||
|
||
// 遍历路径直到倒数第二个部分
|
||
for i := 0; i < len(pathParts)-1; i++ {
|
||
key := pathParts[i]
|
||
existingValue, exists := currentData[key]
|
||
|
||
if !exists {
|
||
// 如果不存在,创建一个新的map
|
||
newMap := make(map[string]interface{})
|
||
currentData[key] = newMap
|
||
currentData = newMap
|
||
} else if nextMap, ok := existingValue.(map[string]interface{}); ok {
|
||
// 如果已经是map,继续向下遍历
|
||
currentData = nextMap
|
||
} else {
|
||
// 如果不是map,替换为新的map
|
||
newMap := make(map[string]interface{})
|
||
currentData[key] = newMap
|
||
currentData = newMap
|
||
}
|
||
}
|
||
|
||
// 设置最终值
|
||
finalKey := pathParts[len(pathParts)-1]
|
||
|
||
// 将JSONBaseObject转换为interface{}
|
||
var interfaceValue interface{}
|
||
switch v := value.(type) {
|
||
case *JSONObject:
|
||
interfaceValue = v.data
|
||
case *JSONArray:
|
||
interfaceValue = v.data
|
||
case *JSONString:
|
||
interfaceValue = v.Value()
|
||
case *JSONNumber:
|
||
interfaceValue = v.Value()
|
||
case *JSONBool:
|
||
interfaceValue = v.Value()
|
||
case *JSONNull:
|
||
interfaceValue = v.Value()
|
||
default:
|
||
interfaceValue = v
|
||
}
|
||
|
||
currentData[finalKey] = interfaceValue
|
||
return nil
|
||
}
|
||
|
||
// 在JSONArray中设置属性
|
||
func setInJSONArray(arr *JSONArray, propertyPath string, value JSONBaseObject) error {
|
||
// 解析路径,第一部分应该是数组索引
|
||
parts := strings.Split(propertyPath, ".")
|
||
|
||
indexStr := parts[0]
|
||
index, err := strconv.Atoi(indexStr)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 获取数组元素
|
||
element, exists := arr.Get(index)
|
||
if !exists {
|
||
return nil // 索引不存在
|
||
}
|
||
|
||
// 如果有后续路径部分,说明要设置嵌套对象
|
||
if len(parts) > 1 {
|
||
remainingPath := strings.Join(parts[1:], ".")
|
||
|
||
// 检查元素类型并递归设置
|
||
switch elem := element.(type) {
|
||
case map[string]interface{}:
|
||
tempObj := &JSONObject{data: elem}
|
||
return SetProperty(tempObj, remainingPath, value)
|
||
case []interface{}:
|
||
tempArr := &JSONArray{data: elem}
|
||
return SetProperty(tempArr, remainingPath, value)
|
||
default:
|
||
// 其他类型无法设置属性
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// 如果没有更多路径部分,直接设置数组元素
|
||
var interfaceValue interface{}
|
||
switch v := value.(type) {
|
||
case *JSONObject:
|
||
interfaceValue = v.data
|
||
case *JSONArray:
|
||
interfaceValue = v.data
|
||
case *JSONString:
|
||
interfaceValue = v.Value()
|
||
case *JSONNumber:
|
||
interfaceValue = v.Value()
|
||
case *JSONBool:
|
||
interfaceValue = v.Value()
|
||
case *JSONNull:
|
||
interfaceValue = v.Value()
|
||
default:
|
||
interfaceValue = v
|
||
}
|
||
|
||
return arr.Put(index, interfaceValue)
|
||
}
|
||
|
||
// 将interface{}转换为适当的JSONBaseObject
|
||
func convertToJSONBaseObject(value interface{}) JSONBaseObject {
|
||
switch v := value.(type) {
|
||
case map[string]interface{}:
|
||
jsonObj := NewJSONObject()
|
||
jsonObj.data = v
|
||
return jsonObj
|
||
case []interface{}:
|
||
jsonArr := NewJSONArray()
|
||
jsonArr.data = v
|
||
return jsonArr
|
||
case string:
|
||
return NewJSONString(v)
|
||
case float64:
|
||
return NewJSONNumber(v)
|
||
case bool:
|
||
return NewJSONBool(v)
|
||
case nil:
|
||
return NewJSONNull()
|
||
default:
|
||
// 默认转换为字符串
|
||
return NewJSONString(stringify(v))
|
||
}
|
||
}
|
||
|
||
// stringify 将任意值转换为字符串表示
|
||
func stringify(value interface{}) string {
|
||
if value == nil {
|
||
return "null"
|
||
}
|
||
switch v := value.(type) {
|
||
case string:
|
||
return v
|
||
case float64:
|
||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||
case bool:
|
||
return strconv.FormatBool(v)
|
||
default:
|
||
return ""
|
||
}
|
||
} |