当前位置:首页 > 文章列表 > Golang > Go教程 > Go SJSON 怎么用 SetRaw 替换完整根 JSON

Go SJSON 怎么用 SetRaw 替换完整根 JSON

来源:17golang原创 2026-10-13 16:12:04 0浏览 收藏

如果你的目标是把一段完整的 JSON 对象或数组替换成新的根文档,sjson.SetRaw 并不是直接的根替换 API。它要求传入一个非空路径,空路径会返回 path cannot be empty。完整根 JSON 已经是最终文本时,应该在调用方完成必要的合法性判断后直接返回或写出这段文本;只有要把原始 JSON 放进某个字段,才使用 SetRaw。

官方地址:https://github.com/tidwall/sjson

记住一个判断:完整根文档替换不需要“根路径”,因为 SJSON 不接受空路径;字段级写入才需要使用 SetRaw(json, path, raw)。如果输入是 []byte,对应使用 SetRawBytes,并继续检查返回的错误。

先把“根替换”和“字段写入”分开

SJSON 的定位是按路径设置 JSON 值。路径可以是 profile.name、items.0 这样的点号表达式;SetRaw 只是把最后写入的值当作已经序列化好的 JSON 片段,不会把它再包成字符串。

目标合适的做法原因
整段 JSON 对象或数组替换根文档直接返回或写出原始 JSON根没有可传给 SJSON 的非空字段路径
把对象写入 payload 字段SetRaw(json, "payload", raw)原始片段会作为对象或数组写入字段
在嵌套路径写入预序列化值SetRaw(json, "data.item", raw)路径明确,适合局部更新
输入和输出都是字节切片SetRawBytes减少字符串与字节切片之间的转换
SJSON 空文档、根路径、SetRaw、原始 JSON 对象和数组之间的关系说明图
图1:SJSON SetRaw 的路径与根 JSON 边界说明图,不是运行截图。

为什么空路径不能代表完整根节点

从实现语义看,SetRaw 的参数顺序是“现有 JSON、路径、原始值”。路径为空时,SJSON 会直接返回 path cannot be empty,而不是把第三个参数理解为整个文档。因此下面的写法不能实现根替换:

package main

import (
    "fmt"

    "github.com/tidwall/sjson"
)

func main() {
    oldJSON := `{"old":true}`
    newJSON := `{"items":[1,2,3]}`

    // 空路径没有字段定位含义,SetRaw 会返回 path cannot be empty。
    result, err := sjson.SetRaw(oldJSON, "", newJSON)
    if err != nil {
        // 生产代码应保留错误,让调用方决定是否走根文档替换分支。
        fmt.Println("不能使用空路径替换根文档:", err)
        return
    }

    // 只有路径有效时才使用 SJSON 返回的新文本。
    fmt.Println(result)
}

这里的失败不是因为 newJSON 是对象或数组,也不是因为它使用了原始 JSON 文本,而是因为“根节点”并不等于一个可解析的字段路径。不要通过给路径加一个虚构的 root 字段来绕过这个限制,否则得到的是 {"root":{...}} 这样的包装对象,根结构已经改变。

完整根 JSON 应该怎样替换

当输入值本身就是新的完整文档时,最小方案是把根替换当成普通文本边界处理。是否调用 encoding/json.Valid 取决于这段 JSON 的信任来源;来自外部请求或文件的内容应先由业务层判断,已经在上游完成约束的内部数据则可以直接转发。

package main

import (
    "encoding/json"
    "errors"
)

// replaceRootJSON 只负责根文档边界,不把完整 JSON 伪装成 SJSON 字段。
func replaceRootJSON(raw []byte) ([]byte, error) {
    if !json.Valid(raw) {
        // 这里把非法输入挡在输出边界之前,避免写出无法解析的文档。
        return nil, errors.New("invalid root json")
    }

    // 调用方拥有这段字节的生命周期时,可以直接返回原始内容。
    return raw, nil
}

如果输出需要独立持有,可在返回前复制一份;如果代码只是把内容写到响应或文件,也可以由写入层负责消费它。重点是不要为了“使用 SetRaw”而人为添加字段。

字段级写入才使用 SetRaw

当原始片段要进入一个字段时,SetRaw 就适合发挥作用。它与 Set 的差别是:Set 会根据 Go 值进行 JSON 编码,而 SetRaw 接受调用方已经准备好的 JSON 片段。下面的例子把对象和数组分别写入两个字段:

package main

import (
    "fmt"

    "github.com/tidwall/sjson"
)

func main() {
    document := `{"meta":{"source":"api"}}`
    rawObject := `{"id":7,"name":"go"}`
    rawArray := `["draft","published"]`

    // SetRaw 把对象片段按 JSON 对象写入 payload,而不是写成带引号的字符串。
    document, err := sjson.SetRaw(document, "payload", rawObject)
    if err != nil {
        // 任何路径或输入问题都要停止继续拼接,避免覆盖已有文档。
        panic(err)
    }

    // 使用 -1 追加到数组需要先有数组字段;这里直接更新已有的状态数组。
    document, err = sjson.SetRaw(document, "states", rawArray)
    if err != nil {
        // 保留第二次写入的错误,调用方可以记录原始文档并回滚。
        panic(err)
    }

    // 结果仍然是一个完整 JSON 文本,但根文档没有被替换。
    fmt.Println(document)
}

这个例子产生的是一个带有 meta、payload 和 states 字段的对象。它证明的是“在根对象下面写字段”,不是“用 rawObject 替换根对象”。如果业务真的要让结果直接变成 {"id":7,"name":"go"},就应该走上一节的根文本替换函数。

字符串和字节切片怎样选择

字符串接口适合配置、模板或已经在字符串层处理的内容;当数据从网络、文件或消息队列以 []byte 形式进入时,可以使用 SetRawBytes,减少中间转换。两者仍然共享同一个路径语义:路径必须非空。

package main

import (
    "fmt"

    "github.com/tidwall/sjson"
)

func addPayload(document []byte, payload []byte) ([]byte, error) {
    // SetRawBytes 直接接收原始字节,并把它写入 data.payload 字段。
    updated, err := sjson.SetRawBytes(document, "data.payload", payload)
    if err != nil {
        // 错误返回时不要把 updated 当成成功结果继续发送。
        return nil, fmt.Errorf("set data.payload: %w", err)
    }

    // updated 可能是重新分配后的切片,调用方应使用返回值而不是旧切片。
    return updated, nil
}

如果你使用 Options.ReplaceInPlace,还要遵守官方实现对输入切片失效的约定:输入可能被原地修改,调用方不能继续依赖旧切片内容。这个选项属于性能取舍,不会改变“空路径不能做根替换”的规则。

SJSON SetRaw、SetRawBytes、根对象根数组和嵌套路径的选择关系图
图2:SJSON 根文档替换与字段级写入的选择关系说明图,不是运行截图。

推荐的落地流程

  1. 先判断需求是替换完整根文档,还是更新某个字段。
  2. 完整根文档直接走文本或字节输出边界,不给 SJSON 构造虚假的根路径。
  3. 字段值已经是 JSON 片段时使用 SetRaw 或 SetRawBytes。
  4. 每次调用都处理 error,并使用函数返回的新字符串或新字节切片。
  5. 来自外部的数据在业务边界判断合法性;不要把 SJSON 的路径操作当成 JSON 校验器。

常见误区

把空字符串当作根路径可以吗?

不可以。SJSON 会把空路径判定为非法路径并返回错误。根替换应由调用方直接处理。

SetRaw 会自动校验 raw 参数吗?

不要把它当作完整的 JSON 校验器。官方说明它把值作为原始 JSON 块写入指定路径,生产代码应在自己的输入边界决定是否先校验。

给路径写成 root 就等价于根替换吗?

不等价。root 是一个真实字段名,结果会多一层对象包装;只有当你的数据模型确实需要这个字段时才这样写。

Set 和 SetRaw 怎样选?

Go 值需要由库负责编码时用 Set;手头已经有合法的 JSON 对象、数组或其他原始片段时用 SetRaw。两者都需要明确的非空路径。

速查表

问题建议
完整根 JSON 变成另一段对象或数组直接返回或写出 raw,必要时先由业务层校验
对象片段写入某个字段sjson.SetRaw(json, "field", raw)
字节切片直接更新字段sjson.SetRawBytes(json, "field", raw)
调用返回错误停止继续发布结果,保留原文并处理错误
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go GJSON 大整数使用 Float 后为什么丢失精度Go GJSON 大整数使用 Float 后为什么丢失精度
上一篇
Go GJSON 大整数使用 Float 后为什么丢失精度
Go SJSON 怎么把已有 JSON 对象直接写入字段
下一篇
Go SJSON 怎么把已有 JSON 对象直接写入字段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    460次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    521次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    539次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    488次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    307次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码