From 7ee90f3a1807dfc2acb93fb2a6575459af697aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=B9=BF?= Date: Wed, 11 Feb 2026 17:32:20 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(gjson):=20=E6=B7=BB=E5=8A=A0Stringif?= =?UTF-8?q?y=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96GetProperty/SetPr?= =?UTF-8?q?operty=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加了Stringify、PrettyPrint和Compact函数,用于将JSONBaseObject 转换为格式化的JSON字符串。同时优化了GetProperty和SetProperty函数的 内部实现,改进了嵌套对象的访问逻辑,并更新了example/main.go以演示 新功能的使用方法。 ``` --- example/main.go | 34 +++++++++++++--- property.go | 84 +++++++++++++++++++++------------------- stringify.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 45 deletions(-) create mode 100644 stringify.go diff --git a/example/main.go b/example/main.go index a425748..9faecc9 100644 --- a/example/main.go +++ b/example/main.go @@ -30,6 +30,18 @@ func main() { jsonStr, _ := obj.ToJSON() fmt.Printf("JSON对象: %s\n", jsonStr) + // 使用Stringify函数 + stringified, _ := gjson.Stringify(obj) + fmt.Printf("Stringify结果: %s\n", stringified) + + // 使用PrettyPrint格式化输出 + pretty, _ := gjson.PrettyPrint(obj) + fmt.Printf("格式化输出:\n%s\n", pretty) + + // 使用Compact函数 + compact, _ := gjson.Compact(obj) + fmt.Printf("紧凑格式: %s\n", compact) + // 从JSON字符串创建对象 newObj := gjson.NewJSONObject() newObj.FromJSON(jsonStr) @@ -79,6 +91,10 @@ func main() { arrayJson, _ := jsonArray.ToJSON() fmt.Printf("JSON数组: %s\n", arrayJson) + // 使用Stringify格式化数组 + arrayStringified, _ := gjson.Stringify(jsonArray, " ") + fmt.Printf("格式化数组:\n%s\n", arrayStringified) + // 访问数组元素 firstElement, _ := jsonArray.Get(0) fmt.Printf("第一个元素: %v\n", firstElement) @@ -89,12 +105,20 @@ func main() { fmt.Printf("嵌套对象属性: %s\n", str.Value()) } - // 演示各种值类型 + // 演示各种值类型的Stringify nullValue := gjson.NewJSONNull() - nullStr, _ := nullValue.ToString() - fmt.Printf("空值: %s\n", nullStr) + nullStr, _ := gjson.Stringify(nullValue) + fmt.Printf("空值Stringify: %s\n", nullStr) boolValue := gjson.NewJSONBool(true) - boolStr, _ := boolValue.ToString() - fmt.Printf("布尔值: %s\n", boolStr) + boolStr, _ := gjson.Stringify(boolValue) + fmt.Printf("布尔值Stringify: %s\n", boolStr) + + numValue := gjson.NewJSONNumber(42.5) + numStr, _ := gjson.Stringify(numValue) + fmt.Printf("数字Stringify: %s\n", numStr) + + strValue := gjson.NewJSONString("hello world") + strStr, _ := gjson.Stringify(strValue) + fmt.Printf("字符串Stringify: %s\n", strStr) } \ No newline at end of file diff --git a/property.go b/property.go index 48fe916..40d7700 100644 --- a/property.go +++ b/property.go @@ -5,7 +5,7 @@ import ( "strings" ) -// getProperty 获取属性值 +// GetProperty 获取属性值 func GetProperty(obj JSONBaseObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) { // 首先尝试将obj转换为其实际类型 switch v := obj.(type) { @@ -19,7 +19,7 @@ func GetProperty(obj JSONBaseObject, propertyPath string, defaultValue JSONBaseO } } -// setProperty 设置属性值 +// SetProperty 设置属性值 func SetProperty(obj JSONBaseObject, propertyPath string, value JSONBaseObject) error { switch v := obj.(type) { case *JSONObject: @@ -35,33 +35,31 @@ func SetProperty(obj JSONBaseObject, propertyPath string, value JSONBaseObject) // 从JSONObject中获取属性 func getFromJSONObject(obj *JSONObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) { pathParts := strings.Split(propertyPath, ".") - currentObj := obj + currentData := obj.data - // 遍历路径直到倒数第二个部分 - for i := 0; i < len(pathParts)-1; i++ { + // 遍历路径直到到达最终部分 + for i := 0; i < len(pathParts); i++ { key := pathParts[i] - value, exists := currentObj.Get(key) + value, exists := currentData[key] if !exists { return defaultValue, nil } - // 如果路径中间部分不是JSONObject,则无法继续 - if jsonObj, ok := value.(*JSONObject); ok { - currentObj = jsonObj + // 如果这是最后一个路径部分,返回值 + if i == len(pathParts)-1 { + return convertToJSONBaseObject(value), nil + } + + // 否则继续深入嵌套对象 + if nextMap, ok := value.(map[string]interface{}); ok { + currentData = nextMap } else { + // 如果路径还没结束但无法继续深入,返回默认值 return defaultValue, nil } } - // 获取最终值 - finalKey := pathParts[len(pathParts)-1] - value, exists := currentObj.Get(finalKey) - if !exists { - return defaultValue, nil - } - - // 根据值的类型返回相应的JSONBaseObject - return convertToJSONBaseObject(value), nil + return defaultValue, nil } // 从JSONArray中获取属性 @@ -88,10 +86,14 @@ func getFromJSONArray(arr *JSONArray, propertyPath string, defaultValue JSONBase // 检查元素类型并递归查找 switch elem := element.(type) { - case *JSONObject: - return getFromJSONObject(elem, remainingPath, defaultValue) - case *JSONArray: - return getFromJSONArray(elem, remainingPath, defaultValue) + 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 @@ -105,26 +107,26 @@ func getFromJSONArray(arr *JSONArray, propertyPath string, defaultValue JSONBase // 在JSONObject中设置属性 func setInJSONObject(obj *JSONObject, propertyPath string, value JSONBaseObject) error { pathParts := strings.Split(propertyPath, ".") - currentObj := obj + currentData := obj.data // 遍历路径直到倒数第二个部分 for i := 0; i < len(pathParts)-1; i++ { key := pathParts[i] - existingValue, exists := currentObj.Get(key) + existingValue, exists := currentData[key] if !exists { - // 如果不存在,创建一个新的JSONObject - newObj := NewJSONObject() - currentObj.Put(key, newObj) - currentObj = newObj - } else if jsonObj, ok := existingValue.(*JSONObject); ok { - // 如果已经是JSONObject,继续向下遍历 - currentObj = jsonObj + // 如果不存在,创建一个新的map + newMap := make(map[string]interface{}) + currentData[key] = newMap + currentData = newMap + } else if nextMap, ok := existingValue.(map[string]interface{}); ok { + // 如果已经是map,继续向下遍历 + currentData = nextMap } else { - // 如果不是JSONObject,替换为新的JSONObject - newObj := NewJSONObject() - currentObj.Put(key, newObj) - currentObj = newObj + // 如果不是map,替换为新的map + newMap := make(map[string]interface{}) + currentData[key] = newMap + currentData = newMap } } @@ -150,7 +152,7 @@ func setInJSONObject(obj *JSONObject, propertyPath string, value JSONBaseObject) interfaceValue = v } - currentObj.Put(finalKey, interfaceValue) + currentData[finalKey] = interfaceValue return nil } @@ -177,10 +179,12 @@ func setInJSONArray(arr *JSONArray, propertyPath string, value JSONBaseObject) e // 检查元素类型并递归设置 switch elem := element.(type) { - case *JSONObject: - return SetProperty(elem, remainingPath, value) - case *JSONArray: - return SetProperty(elem, remainingPath, value) + 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 diff --git a/stringify.go b/stringify.go new file mode 100644 index 0000000..a14573a --- /dev/null +++ b/stringify.go @@ -0,0 +1,101 @@ +package gjson + +import ( + "encoding/json" +) + +// Stringify 将JSONBaseObject转换为格式化的JSON字符串 +// 类似于JavaScript中的JSON.stringify函数 +func Stringify(obj JSONBaseObject, space ...string) (string, error) { + var indent string + if len(space) > 0 { + indent = space[0] + } else { + indent = "" // 默认无缩进 + } + + // 根据不同的对象类型进行处理 + switch v := obj.(type) { + case *JSONObject: + if indent != "" { + // 格式化带缩进的JSON + bytes, err := json.MarshalIndent(v.data, "", indent) + if err != nil { + return "", err + } + return string(bytes), nil + } else { + // 紧凑型JSON + bytes, err := json.Marshal(v.data) + if err != nil { + return "", err + } + return string(bytes), nil + } + case *JSONArray: + if indent != "" { + // 格式化带缩进的JSON + bytes, err := json.MarshalIndent(v.data, "", indent) + if err != nil { + return "", err + } + return string(bytes), nil + } else { + // 紧凑型JSON + bytes, err := json.Marshal(v.data) + if err != nil { + return "", err + } + return string(bytes), nil + } + case *JSONString: + return v.ToJSON() + case *JSONNumber: + return v.ToJSON() + case *JSONBool: + return v.ToJSON() + case *JSONNull: + return v.ToJSON() + default: + // 如果是其他类型,尝试转换为JSON + bytes, err := json.Marshal(v) + if err != nil { + return "", err + } + return string(bytes), nil + } +} + +// StringifySimple 简单的字符串化函数,将任何值转换为JSON字符串 +func StringifySimple(value interface{}, space ...string) (string, error) { + var indent string + if len(space) > 0 { + indent = space[0] + } else { + indent = "" // 默认无缩进 + } + + if indent != "" { + bytes, err := json.MarshalIndent(value, "", indent) + if err != nil { + return "", err + } + return string(bytes), nil + } else { + bytes, err := json.Marshal(value) + if err != nil { + return "", err + } + return string(bytes), nil + } +} + +// PrettyPrint 格式化打印JSON对象 +func PrettyPrint(obj JSONBaseObject) (string, error) { + return Stringify(obj, " ") // 使用两个空格作为缩进 +} + +// Compact 将JSON对象转换为紧凑格式(无多余空白字符) +func Compact(obj JSONBaseObject) (string, error) { + return Stringify(obj) // 无缩进的格式 +} \ No newline at end of file