python 基础之 jsonpatch 用于对 JSON 文档的局部更新操作

Python中JSON Patch的使用(jsonpatch库)

Python的jsonpatch库是实现RFC 6902标准的JSON Patch工具,支持通过patch操作修改JSON文档、生成diff补丁、反向操作等功能,广泛用于API数据更新、配置同步等场景。

一、安装jsonpatch库

首先通过pip安装:

bash 复制代码
pip install jsonpatch

同时建议安装jsonpointer(JSON Patch依赖的路径解析库,通常会随jsonpatch自动安装)。

二、核心用法

1. 基础操作:应用Patch修改JSON

通过定义patch操作数组,对原始JSON文档执行修改:

python 复制代码
import jsonpatch

# 原始JSON文档
original = {
    "users": [
        {"id": 1, "name": "Charlie"},
        {"id": 2, "name": "Alice"}
    ],
    "config": {"theme": "light"}
}

# 定义JSON Patch操作数组(遵循RFC 6902)
patch = [
    {"op": "replace", "path": "/config/theme", "value": "dark"},  # 修改主题
    {"op": "add", "path": "/users/-", "value": {"id": 3, "name": "Bob"}},  # 添加用户(-表示数组末尾)
    {"op": "remove", "path": "/users/0"},  # 删除第一个用户
    {"op": "test", "path": "/users/0/name", "value": "Alice"}  # 验证值(确保操作原子性)
]

# 应用patch
patched = jsonpatch.apply_patch(original, patch)
print(json.dumps(patched, indent=2))

输出结果

json 复制代码
{
  "users": [
    {"id": 2, "name": "Alice"},
    {"id": 3, "name": "Bob"}
  ],
  "config": {"theme": "dark"}
}

2. 生成Patch(通过两个文档的diff)

自动对比原始文档和目标文档,生成差异patch:

python 复制代码
import jsonpatch

# 原始文档
original = {"a": 1, "b": 2, "c": [1, 2, 3]}

# 目标文档
target = {"a": 1, "b": 3, "c": [1, 4]}

# 生成diff patch
patch = jsonpatch.make_patch(original, target)

# 打印patch操作数组
print("生成的Patch:", patch.patch)
# 应用patch验证结果
print("应用Patch后:", patch.apply(original))

输出

复制代码
生成的Patch: [{'op': 'replace', 'path': '/b', 'value': 3}, {'op': 'replace', 'path': '/c/1', 'value': 4}, {'op': 'remove', 'path': '/c/2'}]
应用Patch后: {'a': 1, 'b': 3, 'c': [1, 4]}

3. 反向Patch(撤销修改)

生成已应用patch的反向操作,用于回滚修改:

python 复制代码
# 基于之前的patch生成反向操作
reverse_patch = patch.reverse

# 回滚修改(从target恢复到original)
reverted = reverse_patch.apply(target)
print("回滚后:", reverted)  # 输出原始文档

4. 单个Patch操作(使用JsonPatch对象)

通过JsonPatch类封装操作,支持分步执行和更灵活的控制:

python 复制代码
from jsonpatch import JsonPatch

# 定义patch对象
patch = JsonPatch([
    {"op": "add", "path": "/new_key", "value": "new_value"},
    {"op": "copy", "from": "/b", "path": "/copied_b"}  # 复制/b到/copied_b
])

# 应用到文档
doc = {"a": 1, "b": 2}
result = patch.apply(doc)
print(result)  # {'a': 1, 'b': 2, 'new_key': 'new_value', 'copied_b': 2}

三、支持的操作类型(完整列表)

操作类型 作用 示例
add 添加元素(数组/对象) {"op":"add","path":"/users/-","value":{"id":3}}
remove 删除元素 {"op":"remove","path":"/users/0"}
replace 替换元素值 {"op":"replace","path":"/config/theme","value":"dark"}
move 移动元素(from→path) {"op":"move","from":"/a","path":"/b/a"}
copy 复制元素(from→path) {"op":"copy","from":"/users/1","path":"/backup/0"}
test 验证值(失败则抛异常) {"op":"test","path":"/b","value":2}

四、错误处理

当patch操作无效(如路径不存在、类型不匹配)时,会抛出JsonPatchExceptionJsonPointerException

python 复制代码
import jsonpatch
from jsonpatch import JsonPatchException
from jsonpointer import JsonPointerException

original = {"a": 1}
patch = [{"op": "replace", "path": "/non_existent", "value": 2}]

try:
    result = jsonpatch.apply_patch(original, patch)
except JsonPointerException as e:
    print("路径错误:", e)  # 路径不存在
except JsonPatchException as e:
    print("Patch错误:", e)  # 操作无效

五、高级场景:与API结合

在REST API中,客户端可发送JSON Patch数组实现资源局部更新(替代PUT全量更新):

python 复制代码
# 服务端示例(Flask)
from flask import Flask, request, jsonify
import jsonpatch

app = Flask(__name__)

# 模拟数据库中的资源
data = {"id": 1, "name": "Product", "price": 100}

@app.route("/products/1", methods=["PATCH"])
def update_product():
    patch = request.json  # 客户端发送的patch数组
    try:
        global data
        data = jsonpatch.apply_patch(data, patch)
        return jsonify(data), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 400

if __name__ == "__main__":
    app.run(debug=True)

客户端发送PATCH请求示例:

bash 复制代码
curl -X PATCH http://localhost:5000/products/1 \
  -H "Content-Type: application/json" \
  -d '[{"op":"replace","path":"/price","value":120},{"op":"add","path":"/stock","value":100}]'

六、注意事项

  1. 数组路径/users/-表示向数组末尾添加元素,/users/0表示第一个元素;
  2. 原子性test操作可用于验证前置条件(如版本号),确保patch仅在数据未被修改时执行;
  3. 性能:对于超大JSON文档,建议使用流式处理或分段patch,避免内存占用过高。

jsonpatch库是Python中处理JSON增量更新的首选工具,完全遵循标准且易用性高,适合各类需要局部修改JSON的场景。

相关推荐
FeiHuo565151 小时前
微信个人号API二次开发:如何提高开发效率和质量
java·开发语言·python·php
jingshaoqi_ccc1 小时前
ubuntu 24桌面系统下交叉编译QT6.9.1
linux·运维·ubuntu
凤凰战士芭比Q1 小时前
Linux内核(升级、编译)
linux·运维·arm开发
wsj__WSJ1 小时前
Python 项目管理工具 uv 详解
python·conda·virtualenv
XH-hui1 小时前
【打靶日记】群内靶机 Word
linux·网络安全
Brixy1 小时前
Linux网络配置
linux·运维·网络
知识分享小能手1 小时前
CentOS Stream 9入门学习教程,从入门到精通,Linux操作系统概述 —全面知识点详解(1)
linux·学习·centos
永不停歇的蜗牛1 小时前
解决方法:在本地电脑安装的Centos虚拟机上启动redis服务,使用本地电脑客户端无法连接到redis。
linux·redis·centos
ayaya_mana1 小时前
EasyTier自建服务器教程:打造低延迟游戏局域网
linux·运维·服务器·windows·游戏·p2p