Go JSONPatch 怎样把 JSON Patch 操作应用到文档
Go 中应用 JSON Patch,核心流程是先用 DecodePatch 解析 RFC 6902 补丁数组,再调用 Patch.Apply 把这些操作按数组顺序作用到原始 JSON 文档上。解析失败或某一步路径不满足操作条件时,应保留错误,不要把原文档误当成已更新结果。
官方地址:https://github.com/evanphx/json-patch
- 补丁是操作数组,
add、remove、replace等操作按顺序影响同一个目标文档。 DecodePatch只负责把 JSON 补丁解析成Patch,真正修改文档要调用Apply或ApplyWithOptions。- 缺失路径是否容忍、是否自动补齐 add 路径、copy 是否限制扩张,都应通过选项明确表达。
先把 JSON Patch 的输入边界分清
JSON Patch 不是一组散落的字段,而是一个 JSON 数组。数组中的每个对象至少包含 op 和 path,必要时再带 value、from 等成员。RFC 6902 定义的操作包括 add、remove、replace、move、copy 和 test;它们会按数组顺序处理,前一个操作产生的文档状态会成为后一个操作的输入。
因此,应用函数需要两份独立数据:一份是补丁数组,另一份是被修改的原始文档。路径使用 JSON Pointer 语义,例如 /profile/name 指向对象的嵌套字段,数组位置则要注意操作前后的索引变化。

用 DecodePatch 解析补丁并调用 Apply
安装当前模块路径后,最小用法是先解析补丁,再应用到原始字节。下面的示例同时替换姓名并删除年龄字段,代码中的错误处理保留了“解析错误”和“应用错误”两个边界:
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch/v5"
)
func main() {
original := []byte(`{"name":"Lin","age":30,"city":"Suzhou"}`)
patchJSON := []byte(`[
{"op":"replace","path":"/name","value":"Ming"},
{"op":"remove","path":"/age"}
]`)
// 先把 JSON 数组解析为有序的 Patch,格式错误在这里返回。
patch, err := jsonpatch.DecodePatch(patchJSON)
if err != nil {
panic(fmt.Errorf("解析补丁失败: %w", err))
}
// Apply 返回新的 JSON 字节;应用阶段的路径错误必须单独处理。
modified, err := patch.Apply(original)
if err != nil {
panic(fmt.Errorf("应用补丁失败: %w", err))
}
// 这里保留 JSON 结果,业务层可以再做反序列化和字段校验。
fmt.Println(string(modified))
}
这个调用不会要求你先把原文档反序列化成 Go 结构体,适合在接口层先处理部分更新,再把结果交给后续业务模型。若结果需要格式化输出,可使用 ApplyIndent;若只想比较两个 JSON 是否结构相等,可使用库提供的 Equal,不要直接比较字节串的空格和键顺序。
用 ApplyOptions 明确容错边界
默认行为更适合发现客户端补丁错误:例如 remove 指向不存在的位置时,应用会返回错误。需要兼容不同版本文档时,可以用 ApplyWithOptions 显式配置,而不是在外层捕获错误后静默忽略:
func applyPatchWithPolicy(document, patchJSON []byte) ([]byte, error) {
// DecodePatch 负责校验补丁的 JSON 形状和操作结构。
patch, err := jsonpatch.DecodePatch(patchJSON)
if err != nil {
return nil, fmt.Errorf("解析 JSON Patch: %w", err)
}
options := jsonpatch.NewApplyOptions()
// 只有确认删除目标可选时,才允许忽略缺失的 remove 路径。
options.AllowMissingPathOnRemove = true
// 允许 add 自动创建中间路径时,要同步评估数据模型约束。
options.EnsurePathExistsOnAdd = true
// copy 的累计扩张可以设置上限,避免不受控地复制大对象。
options.AccumulatedCopySizeLimit = 1
AllowMissingPathOnRemove 适合“删除动作重复到达也不算失败”的场景;EnsurePathExistsOnAdd 则会影响缺少中间对象时的 add 行为。两者都可能放宽输入约束,生产接口仍应在应用前限制允许的路径和操作集合。

把结果接回业务对象时保留错误边界
应用完成后通常有两种接法:继续把 JSON 字节转发给下游,或反序列化为结构体做业务校验。后者不要只检查 json.Unmarshal 是否成功,因为 JSON 结构合法不代表状态满足业务规则。
| 阶段 | 建议动作 | 失败含义 |
|---|---|---|
| 解析补丁 | DecodePatch 返回错误即拒绝 | 补丁 JSON 或操作结构不合法 |
| 应用补丁 | 检查 Apply 错误 | 路径、索引或 test 条件不满足 |
| 业务转换 | 反序列化后再做字段校验 | 文档合法但不符合业务模型 |
如果补丁来自外部请求,建议将允许的根路径、操作类型和文档大小写进接口契约;JSON Patch 只描述如何修改文档,并不会替代权限校验、字段白名单或并发版本控制。
常见问题
Patch.Apply 会原地修改传入的字节吗?
调用方应把返回的字节视为新文档,并以返回值为准;不要忽略返回结果,也不要把原始输入当成已经更新。
为什么 remove 有时会返回路径错误?
默认策略要求目标路径存在。只有明确允许幂等删除时,才考虑通过 AllowMissingPathOnRemove 放宽该行为。
JSON Patch 和 JSON Merge Patch 是一回事吗?
不是。JSON Patch 是带操作和路径的数组,Merge Patch 更接近用对象描述字段合并;本题的 DecodePatch 与 Apply 针对 RFC 6902 JSON Patch。
Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名
- 上一篇
- Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名
- 下一篇
- Go JSONPatch 怎样合并两份 JSON Merge Patch
-
- Golang · Go教程 | 50分钟前 |
- Go LDAP 怎样在修改请求中只替换一个指定属性
- 302浏览 收藏
-
- Golang · Go教程 | 50分钟前 | go · 分页查询 ·
- Go LDAP 怎样用分页查询读取大型目录结果
- 334浏览 收藏
-
- Golang · Go教程 | 53分钟前 |
- Go LDAP 怎样对查询过滤器中的用户输入进行转义
- 135浏览 收藏
-
- Golang · Go教程 | 56分钟前 |
- Go SFTP 怎样限制同一文件传输的并发请求数量
- 232浏览 收藏
-
- Golang · Go教程 | 57分钟前 |
- Go SFTP 怎样用临时文件与重命名完成上传交接
- 355浏览 收藏
-
- Golang · Go教程 | 59分钟前 |
- Go SFTP 怎样流式下载远端文件并保留错误
- 360浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go INI 怎样保留重复键的多个值
- 446浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go INI 怎样把多个配置源按优先级加载
- 210浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go JSONPatch 怎样用 JSON Pointer 表示包含斜杠的键
- 187浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go JSONPatch 怎样合并两份 JSON Merge Patch
- 208浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名
- 139浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 773次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 770次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 855次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 821次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 651次使用
-
- Java 性能优化上线清单:从定位、改造到灰度发布
- 2026-06-11 860浏览
-
- Spring Boot 压测验证:Gatling、JMeter 与性能回归门禁
- 2026-06-11 843浏览
-
- Java NMT 非堆内存排查:Direct Buffer、线程栈与 Metaspace 分析
- 2026-06-11 826浏览
-
- Spring Boot 容器内存优化:JVM 堆、非堆与 MaxRAMPercentage
- 2026-06-11 809浏览
-
- Tomcat 连接与线程参数调优:maxThreads、acceptCount 与 KeepAlive
- 2026-06-11 792浏览
