gjson/property.go

256 lines
6.3 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, ".")
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 ""
}
}