返回列表 发布新帖
查看: 53|回复: 0

Go-SJSON:JSON 动态修改新方案

发表于 5 天前 | 查看全部 |阅读模式

这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 mrkong 于 2025-8-15 16:24 编辑

在 Go 语言的 JSON 处理领域,读取修改 是两个核心需求。前文介绍过的 GJSON 已经很好地解决了灵活读取问题,而它的“姊妹库” SJSON 则专注于实现 无需结构体定义的 JSON 动态修改,与 GJSON 形成完美互补。
本文将从原生方案说起,逐步对比 SJSON 的优势与用法。

一、Go 原生 JSON 修改方式
Go 原生修改 JSON 的流程通常是:
  • 定义结构体
  • json.Unmarshal 将 JSON 解析到结构体
  • 修改字段
  • json.Marshal 转回 JSON

示例:
  1. package main

  2. import (
  3.     "encoding/json"
  4.     "fmt"
  5. )

  6. type Person struct {
  7.     Name string `json:"name"`
  8.     Age  int    `json:"age"`
  9. }

  10. func main() {
  11.     jsonStr := `{"name":"张三","age":25}`

  12.     var person Person
  13.     err := json.Unmarshal([]byte(jsonStr), &person)
  14.     if err != nil {
  15.         fmt.Println("解析错误:", err)
  16.         return
  17.     }

  18.     person.Age = 35
  19.     newJson, _ := json.Marshal(person)

  20.     fmt.Println(string(newJson))
  21. }
复制代码
这种方式虽然类型安全,但在实际业务中存在明显问题:
  • 必须预先定义结构体,缺少灵活性
  • 未定义字段会丢失,难以保持原始结构完整
  • 嵌套结构或动态字段路径处理繁琐


二、SJSON 简介
SJSON 是 tidwall 团队开发的一个轻量库,支持直接通过路径表达式修改 JSON 字符串,无需定义结构体。它与 GJSON 使用相同的路径语法,因此可以无缝组合,实现 JSON 的“读写闭环”。
  • 特点

    • 无需结构体,直接操作 JSON 字符串
    • 支持嵌套结构和数组的修改、追加
    • 保留原有字段,不会丢失未修改的内容
    • 支持动态路径,运行时灵活构建

安装:
  1. go get -u github.com/tidwall/sjson
复制代码
三、SJSON 核心用法
1. 基础值修改
  1. package main

  2. import (
  3.     "fmt"
  4.     "github.com/tidwall/sjson"
  5. )

  6. func main() {
  7.     jsonStr := `{"name":"张三","age":25}`

  8.     // 修改 age 值为 35
  9.     newJson, _ := sjson.Set(jsonStr, "age", 35)

  10.     fmt.Println(newJson)
  11. }
复制代码
2. 嵌套结构修改
  1. package main

  2. import (
  3.     "fmt"
  4.     "github.com/tidwall/sjson"
  5. )

  6. func main() {
  7.     jsonStr := `{
  8.        "name": "张三",
  9.        "age": 25,
  10.        "hobby": {
  11.           "sing": "只因你太美",
  12.           "dance": "背带裤",
  13.           "rap": "kun",
  14.           "ball": "篮球"
  15.        }
  16.     }`

  17.     // 修改 hobby.sing
  18.     newJson, _ := sjson.Set(jsonStr, "hobby.sing", "重生")

  19.     fmt.Println(newJson)
  20. }
复制代码
3. 数组操作
  1. package main

  2. import (
  3.     "fmt"
  4.     "github.com/tidwall/sjson"
  5. )

  6. func main() {
  7.     jsonStr := `{"hobby": ["sing","dance","rap","ball"]}`

  8.     // 修改数组第 4 个元素
  9.     newJson, _ := sjson.Set(jsonStr, "hobby.3", "play")
  10.     fmt.Println(newJson)

  11.     // 追加元素
  12.     newJson, _ = sjson.Set(jsonStr, "hobby.-1", "read")
  13.     fmt.Println(newJson)
  14. }
复制代码
4. 字段删除
  1. package main

  2. import (
  3.     "fmt"
  4.     "github.com/tidwall/sjson"
  5. )

  6. func main() {
  7.     jsonStr := `{"name":"张三","age":25}`

  8.     // 删除 age 字段
  9.     newJson, _ := sjson.Delete(jsonStr, "age")

  10.     fmt.Println(newJson)
  11. }
复制代码

四、SJSON vs 原生方案
对比项Go 原生方案SJSON
结构体定义必须提前定义无需定义
保留未知字段❌ 丢失未定义字段✅ 完全保留
嵌套字段修改繁琐路径直达
动态路径不便灵活支持
性能一般高效,内部优化
总结
  • 如果你需要类型安全、编译期检查,用原生方式更稳妥
  • 如果你需要动态修改、保留原结构、快速迭代,SJSON 无疑是更优选择

五、与 GJSON 组合
由于 GJSON 与 SJSON 使用相同的路径语法,你可以:
GJSON 用于读取:
  1. value := gjson.Get(jsonStr, "hobby.sing").String()
复制代码
SJSON 用于修改:
  1. newJson, _ := sjson.Set(jsonStr, "hobby.sing", "重生")
复制代码
这样即可形成“读取 → 修改 → 输出”的高效链路,完全不需要结构体定义。

六、结语
在动态 JSON 修改场景下,SJSON 可以让我们摆脱结构体的束缚,减少冗余代码,并保持 JSON 的完整性。配合 GJSON 使用,可以极大提升开发效率。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2001-2025 Suike Tech All Rights Reserved. 随客交流社区 (备案号:津ICP备19010126号) |Processed in 0.127646 second(s), 7 queries , Gzip On, MemCached On.
关灯 在本版发帖返回顶部
快速回复 返回顶部 返回列表