当前位置:首页 > 文章列表 > Golang > Go教程 > Go JSONPatch 怎样把 JSON Patch 操作应用到文档

Go JSONPatch 怎样把 JSON Patch 操作应用到文档

来源:17golang原创 2026-10-29 12:33:18 0浏览 收藏

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 指向对象的嵌套字段,数组位置则要注意操作前后的索引变化。

JSON Patch 补丁数组、DecodePatch、Patch、Operation、JSON Pointer 路径、Apply 与目标 JSON 文档的静态结构关系说明图
图1:结构说明图,展示 JSON Patch 输入、操作对象与目标文档之间的关系,不是运行截图。

用 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 行为。两者都可能放宽输入约束,生产接口仍应在应用前限制允许的路径和操作集合。

ApplyOptions 与缺失 remove、自动补齐 add 路径、copy 大小限制和 Apply 的静态边界关系图
图2:边界说明图,展示 ApplyOptions 对路径容错与 copy 扩张的配置关系,不是运行截图。

把结果接回业务对象时保留错误边界

应用完成后通常有两种接法:继续把 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。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名
上一篇
Go Validator 怎样通过 TagNameFunc 在错误中显示 JSON 字段名
Go JSONPatch 怎样合并两份 JSON Merge Patch
下一篇
Go JSONPatch 怎样合并两份 JSON Merge Patch
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    773次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    770次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    855次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    821次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    651次使用