Go-SJSON:JSON 动态修改新方案
本帖最后由 mrkong 于 2025-8-15 16:24 编辑在 Go 语言的 JSON 处理领域,读取 与 修改 是两个核心需求。前文介绍过的 GJSON 已经很好地解决了灵活读取问题,而它的“姊妹库” SJSON 则专注于实现 无需结构体定义的 JSON 动态修改,与 GJSON 形成完美互补。本文将从原生方案说起,逐步对比 SJSON 的优势与用法。
一、Go 原生 JSON 修改方式Go 原生修改 JSON 的流程通常是:
[*]定义结构体
[*]json.Unmarshal 将 JSON 解析到结构体
[*]修改字段
[*]json.Marshal 转回 JSON
示例:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Ageint `json:"age"`
}
func main() {
jsonStr := `{"name":"张三","age":25}`
var person Person
err := json.Unmarshal([]byte(jsonStr), &person)
if err != nil {
fmt.Println("解析错误:", err)
return
}
person.Age = 35
newJson, _ := json.Marshal(person)
fmt.Println(string(newJson))
}这种方式虽然类型安全,但在实际业务中存在明显问题:
[*]必须预先定义结构体,缺少灵活性
[*]未定义字段会丢失,难以保持原始结构完整
[*]嵌套结构或动态字段路径处理繁琐
二、SJSON 简介SJSON 是 tidwall 团队开发的一个轻量库,支持直接通过路径表达式修改 JSON 字符串,无需定义结构体。它与 GJSON 使用相同的路径语法,因此可以无缝组合,实现 JSON 的“读写闭环”。
[*]特点:
[*]无需结构体,直接操作 JSON 字符串
[*]支持嵌套结构和数组的修改、追加
[*]保留原有字段,不会丢失未修改的内容
[*]支持动态路径,运行时灵活构建
安装:go get -u github.com/tidwall/sjson三、SJSON 核心用法
1. 基础值修改
package main
import (
"fmt"
"github.com/tidwall/sjson"
)
func main() {
jsonStr := `{"name":"张三","age":25}`
// 修改 age 值为 35
newJson, _ := sjson.Set(jsonStr, "age", 35)
fmt.Println(newJson)
}
2. 嵌套结构修改
package main
import (
"fmt"
"github.com/tidwall/sjson"
)
func main() {
jsonStr := `{
"name": "张三",
"age": 25,
"hobby": {
"sing": "只因你太美",
"dance": "背带裤",
"rap": "kun",
"ball": "篮球"
}
}`
// 修改 hobby.sing
newJson, _ := sjson.Set(jsonStr, "hobby.sing", "重生")
fmt.Println(newJson)
}
3. 数组操作
package main
import (
"fmt"
"github.com/tidwall/sjson"
)
func main() {
jsonStr := `{"hobby": ["sing","dance","rap","ball"]}`
// 修改数组第 4 个元素
newJson, _ := sjson.Set(jsonStr, "hobby.3", "play")
fmt.Println(newJson)
// 追加元素
newJson, _ = sjson.Set(jsonStr, "hobby.-1", "read")
fmt.Println(newJson)
}
4. 字段删除
package main
import (
"fmt"
"github.com/tidwall/sjson"
)
func main() {
jsonStr := `{"name":"张三","age":25}`
// 删除 age 字段
newJson, _ := sjson.Delete(jsonStr, "age")
fmt.Println(newJson)
}
四、SJSON vs 原生方案
对比项Go 原生方案SJSON
结构体定义必须提前定义无需定义
保留未知字段❌ 丢失未定义字段✅ 完全保留
嵌套字段修改繁琐路径直达
动态路径不便灵活支持
性能一般高效,内部优化
总结:
[*]如果你需要类型安全、编译期检查,用原生方式更稳妥
[*]如果你需要动态修改、保留原结构、快速迭代,SJSON 无疑是更优选择
五、与 GJSON 组合由于 GJSON 与 SJSON 使用相同的路径语法,你可以:GJSON 用于读取:value := gjson.Get(jsonStr, "hobby.sing").String()
SJSON 用于修改:newJson, _ := sjson.Set(jsonStr, "hobby.sing", "重生")
这样即可形成“读取 → 修改 → 输出”的高效链路,完全不需要结构体定义。
六、结语在动态 JSON 修改场景下,SJSON 可以让我们摆脱结构体的束缚,减少冗余代码,并保持 JSON 的完整性。配合 GJSON 使用,可以极大提升开发效率。
页:
[1]