gjson/property.go

252 lines
6.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, ".")
currentObj := obj
// 遍历路径直到倒数第二个部分
for i := 0; i < len(pathParts)-1; i++ {
key := pathParts[i]
value, exists := currentObj.Get(key)
if !exists {
return defaultValue, nil
}
// 如果路径中间部分不是JSONObject则无法继续
if jsonObj, ok := value.(*JSONObject); ok {
currentObj = jsonObj
} else {
return defaultValue, nil
}
}
// 获取最终值
finalKey := pathParts[len(pathParts)-1]
value, exists := currentObj.Get(finalKey)
if !exists {
return defaultValue, nil
}
// 根据值的类型返回相应的JSONBaseObject
return convertToJSONBaseObject(value), 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 *JSONObject:
return getFromJSONObject(elem, remainingPath, defaultValue)
case *JSONArray:
return getFromJSONArray(elem, remainingPath, defaultValue)
default:
// 其他类型无法继续访问属性
return defaultValue, nil
}
}
// 如果没有更多路径部分,直接返回元素
return convertToJSONBaseObject(element), nil
}
// 在JSONObject中设置属性
func setInJSONObject(obj *JSONObject, propertyPath string, value JSONBaseObject) error {
pathParts := strings.Split(propertyPath, ".")
currentObj := obj
// 遍历路径直到倒数第二个部分
for i := 0; i < len(pathParts)-1; i++ {
key := pathParts[i]
existingValue, exists := currentObj.Get(key)
if !exists {
// 如果不存在创建一个新的JSONObject
newObj := NewJSONObject()
currentObj.Put(key, newObj)
currentObj = newObj
} else if jsonObj, ok := existingValue.(*JSONObject); ok {
// 如果已经是JSONObject继续向下遍历
currentObj = jsonObj
} else {
// 如果不是JSONObject替换为新的JSONObject
newObj := NewJSONObject()
currentObj.Put(key, newObj)
currentObj = newObj
}
}
// 设置最终值
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
}
currentObj.Put(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 *JSONObject:
return SetProperty(elem, remainingPath, value)
case *JSONArray:
return SetProperty(elem, 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 ""
}
}