这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 mrkong 于 2025-8-15 16:24 编辑
在 Go 语言的 JSON 处理领域, 读取 与 修改 是两个核心需求。前文介绍过的 GJSON 已经很好地解决了灵活读取问题,而它的“姊妹库” SJSON 则专注于实现 无需结构体定义的 JSON 动态修改,与 GJSON 形成完美互补。 本文将从原生方案说起,逐步对比 SJSON 的优势与用法。
一、Go 原生 JSON 修改方式Go 原生修改 JSON 的流程通常是: 示例:
- package main
- import (
- "encoding/json"
- "fmt"
- )
- type Person struct {
- Name string `json:"name"`
- Age int `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 | 结构体定义 | 必须提前定义 | 无需定义 | 保留未知字段 | ❌ 丢失未定义字段 | ✅ 完全保留 | 嵌套字段修改 | 繁琐 | 路径直达 | 动态路径 | 不便 | 灵活支持 | 性能 | 一般 | 高效,内部优化 |
总结: 五、与 GJSON 组合由于 GJSON 与 SJSON 使用相同的路径语法,你可以: GJSON 用于读取: - value := gjson.Get(jsonStr, "hobby.sing").String()
复制代码SJSON 用于修改: - newJson, _ := sjson.Set(jsonStr, "hobby.sing", "重生")
复制代码这样即可形成“读取 → 修改 → 输出”的高效链路,完全不需要结构体定义。
六、结语在动态 JSON 修改场景下,SJSON 可以让我们摆脱结构体的束缚,减少冗余代码,并保持 JSON 的完整性。配合 GJSON 使用,可以极大提升开发效率。
|