JSON可以说是Web时代最通用的语言,本文汇总Python生态下几个JSON处理库/框架。
| 特点 | json(Python内置) | orjson(高性能) | json5(支持JSON5格式) | jsonpatch |
|---|---|---|---|---|
| 性能 | 较慢,纯Python实现,适合小数据量 | 非常快,C语言实现,序列化快10倍,反序列化快2倍 | 较慢,纯Python实现,性能最低 | 较慢 |
| 序列化结果 | 返回字符串(str) | 返回字节(bytes),需手动转字符串 | 返回字符串(str) | 字符串 |
| 支持数据类型 | 基本Python类型(dict、list、int等) | 支持更多复杂类型(dataclass、datetime、numpy等) | 支持JSON5扩展语法(注释、尾逗号、单引号等) | 基本Python类型 |
| 标准兼容性 | 严格遵守JSON标准(RFC 8259) | 严格遵守JSON标准,不支持NaN和Infinity | 支持JSON5扩展,允许注释、NaN、Infinity等 | RFC 6902 |
| 功能特点 | 内置,无需安装,简单易用 | 高性能,适合大数据和复杂类型处理 | 支持更灵活的JSON5格式,适合配置文件 | JSON编辑、修改 |
| 缺点 | 性能较低,功能有限 | 返回bytes,没文件读写接口,需额外处理 | 性能慢,不适合性能敏感场景 | 不适合性能敏感场景 |
json
Python内置模块,简单易用,适用如下场景:
- 适合小到中等数据量
- 支持文件读写,API简单直观
- 性能一般,序列化大数据时较慢
无需安装,直接看入门示例:
importjson data={"name":"张三","age":30,"is_student":False}# 序列化为JSON字符串,indent=2美化格式,ensure_ascii=False支持中文json_str=json.dumps(data,ensure_ascii=False,indent=2)# 反序列化回Python对象data_back=json.loads(json_str)# 写入JSON文件withopen("data.json","w",encoding="utf-8")asf:json.dump(data,f,ensure_ascii=False,indent=2)# 从文件读取JSONwithopen("data.json","r",encoding="utf-8")asf:data_from_file=json.load(f)orjson
基于Python和Rust的开源(GitHub,8.2K Star,309 Fork)JSON库,相比标准json模块,速度快3-10倍,内存效率更高。建议在高性能Web应用和大规模数据处理场景中优先使用。
核心优势在于其惊人的序列化速度,API设计简洁直观。
实战
基于pip安装:pip install orjson
示例:
importorjson,datetime,numpy data={"type":"job","created_at":datetime.datetime(1970,1,1),"status":"🆗","payload":numpy.array([[1,2],[3,4]]),}json_bytes=orjson.dumps(data,option=orjson.OPT_NAIVE_UTC|orjson.OPT_SERIALIZE_NUMPY)orjson.loads(_)dumps方法直接返回bytes类型,避免编码转换开销,性能提升显著。
反序列化同样快速,支持各种数据类型的精确还原。
json_data=b'{"name": "李四", "scores": [95, 87, 92]}'parsed_data=orjson.loads(json_data)loads方法能够快速解析JSON字节数据,恢复原始数据结构。
完整支持Python主要数据类型,包括datetime和UUID
fromdatetimeimportdatetime,datefromuuidimportuuid4 data={"id":uuid4(),"created_at":datetime.now(),"birthday":date(1995,5,15),"metadata":{"version":1.0,"active":True}}json_output=orjson.dumps(data)原生支持日期时间和UUID类型,无需自定义序列化器。
提供丰富的选项,满足不同场景的性能需求:
data={"message":"性能测试","items":list(range(1000))}# 紧凑模式,去除空白字符compact_json=orjson.dumps(data,option=orjson.OPT_APPEND_NEWLINE)# 按Key排序,确保输出一致性sorted_json=orjson.dumps(data,option=orjson.OPT_SORT_KEYS)对比内置json模块的基准测试:
importorjsonimportjsonimporttime data={"users":[{"id":i,"name":f"user_{i}"}fori inrange(1000)]}# 标准json性能start=time.time()for_ inrange(1000):json.dumps(data)json_time=time.time()-start# orjson性能start=time.time()for_ inrange(1000):orjson.dumps(data)orjson_time=time.time()-startprint(f"标准json:{json_time:.3f}秒")print(f"orjson:{orjson_time:.3f}秒")print(f"性能提升:{json_time/orjson_time:.1f}倍")Web应用集成:
fromflaskimportFlask,Responseimportorjson app=Flask(__name__)@app.route('/api/users')defget_users():users=[{"id":1,"name":"张三","email":"zhang@example.com"},{"id":2,"name":"李四","email":"li@example.com"}]json_data=orjson.dumps(users)returnResponse(json_data,mimetype='application/json')importorjsonimportnumpyasnpdefprocess_large_dataset():# 生成大型数据集large_data={"matrix":np.random.rand(100,100).tolist(),"timestamps":[f"2024-01-{i:02d}"fori inrange(1,32)]}# 快速序列化returnorjson.dumps(large_data)result=process_large_dataset()print(f"序列化数据大小:{len(result)}字节")ujson
开源(GitHub,4.5K Star,386 Fork)使用C++编写、提供Python绑定的超快JSON处理库。
核心技术:
- C语言底层实现,直接操作内存
- 优化的编码/解码算法
- 与标准json模块API完全兼容
安装:pip install ujson
示例:
importujson data={"name":"Alice","age":30}json_str=ujson.dumps(data)data=ujson.loads(json_str)# 支持高级选项json_str=ujson.dumps(data,ensure_ascii=False,# 支持非ASCII字符escape_forward_slashes=False,# 不转义正斜杠indent=2# 格式化输出)simplejson
开源(GitHub,1.7K Star,354 Fork)库,官方文档。
核心技术:
- 支持更多数据类型(datetime、Decimal等)
- 更好的错误处理
- 向后兼容标准库
安装:pip install simplejson
示例:
fromsimplejsonimportdumps,RawJSON payload={"status":"ok","data":RawJSON('{"a": 1, "b": 2}')}dumps(payload)# 支持datetime序列化classDateTimeEncoder(json.JSONEncoder):defdefault(self,obj):ifisinstance(obj,datetime):returnobj.isoformat()returnsuper().default(obj)data={"timestamp":datetime.now()}json_str=json.dumps(data,cls=DateTimeEncoder)RapidJson
RapidJson是腾讯开源(GitHub,15.1K Star,3.6K Fork)使用C++开发、同时提供SAX/DOM风格API的JSON处理库。
核心技术:
- C++底层实现,支持SIMD指令集优化
- 内存池技术减少内存分配
- 支持JSON指针和路径查询
在Python生态下,想使用RapidJson,可通过包装器(Wrapper)来实现。
python-rapidjson
PyPi,最后一个版本1.23,发布于25年12月7日,对应开源(GitHub,533 Star,53 Fork)库。
安装:pip install python-rapidjson
示例:
importrapidjson data={'foo':100,'bar':'baz'}dump_str=rapidjson.dumps(data)rapidjson.loads(dump_str)# 自定义classStream:defwrite(self,data):print("Chunk:",data)rapidjson.dump(data,Stream(),chunk_size=5)# 严格模式解析config=rapidjson.ParseFlagNumbersAsStrings|rapidjson.ParseFlagValidateEncoding data=rapidjson.loads(json_str,parse_mode=config)# 生成带格式的JSONjson_str=rapidjson.dumps(data,indent=4,sort_keys=True,ensure_ascii=False)pyrapidjson
PyPi,最后一个版本0.5.1,发布于17年6月29日,对应开源(GitHub,25 Star,5 Fork)库。
安装:pip install pyrapidjson
json5
对JSON5不了解,可参考JSON衍生:JSON5、JSONL、JSONC、NDJSON、BSON、JSONB、JSONP、HOCON。
PyPi对应开源(GitHub,282 Star,34 Fork)库,能力:
- 支持注释、尾逗号、单引号字符串、未加引号的键等JSON5特性。
- 适合用作配置文件,写起来更灵活方便。
- 性能较慢,不适合对速度要求高的场景。
- API和标准
json非常类似,容易上手。
实战
安装:pip install json5
示例:
importjson5 json5_text=""" { // 这是注释 unquotedKey: '单引号字符串', trailingComma: true, // 尾逗号允许 } """data=json5.loads(json5_text)json5_str=json5.dumps(data,indent=2)如果JSON5格式不正确,会抛出json5.JSON5Error异常。
提供高级选项,以满足更复杂的数据处理需求。比如,可通过传递自定义的编码器和解码器类来改变json5的默认行为:
classCustomEncoder(json5.JSONEncoder):defencode(self,obj):# 自定义编码逻辑returnsuper().encode(obj)classCustomDecoder(json5.JSONDecoder):defdecode(self,obj):# 自定义解码逻辑returnsuper().decode(obj)encoder=CustomEncoder()decoder=CustomDecoder()encoded_data=encoder.encode(data)decoded_data=decoder.decode(encoded_data)jsonpatch
JSON Patch,一种用于描述对JSON文档所做更改的格式。它允许在只有部分数据发生变化时,避免发送整个文档,特别适用于HTTP PATCH方法,可实现HTTP API的部分更新。JSON Patch文档本身也是JSON格式,定义在IETF的RFC 6902中。JSON Patch包括原始文档、补丁和结果。
假设原始文档:
{"baz":"qux","foo":"bar"}应用如下补丁:
[{"op":"replace","path":"/baz","value":"boo"},{"op":"add","path":"/hello","value":["world"]},{"op":"remove","path":"/foo"}]结果是:
{"baz":"boo","hello":["world"]}工作原理:JSON Patch文档是一个包含一系列补丁操作的JSON数组。这些操作按顺序应用,如果任何操作失败,则整个补丁操作应中止。支持操作包括:
add:向对象添加值或将其插入数组中remove:从对象或数组中删除值replace:替换值,相当于先执行remove再执行addmove:将值从一个位置移动到另一个位置copy:将值从文档的一个位置复制到另一个位置test:测试文档中的指定值是否与提供的值相等
JSON Patch使用JSON Pointer来指定操作的目标位置。JSON Pointer是由/分隔的字符串,用于指定对象中的键或数组中的索引。如果需要指向文档的根,则使用空字符串。
在Go生态下,evanphx/json-patch,可将patch应用到JSON文档上;给出2个JSON文档,自动计算差异,生成patch。C++中,jsoncons内置对JSON Patch的支持。
Python生态下,推荐使用开源(GitHub,496 Star,105 Fork)库,官方文档。
实战
基于pip安装:pip install jsonpatch,会一并安装jsonpointer,路径解析库。
示例太简单:
importjsonpatch original={"baz":"qux","foo":"bar"}patch=[{"op":"replace","path":"/baz","value":"boo"},{"op":"add","path":"/hello","value":["world"]},{"op":"remove","path":"/foo"}]# 应用patchpatched=jsonpatch.apply_patch(original,patch)print(json.dumps(patched,indent=2))JsonPatch对象
fromjsonpatchimportJsonPatch patch=JsonPatch([{"op":"add","path":"/new_key","value":"new_value"},{"op":"copy","from":"/b","path":"/copied_b"}])doc={"a":1,"b":2}result=patch.apply(doc)print(result)通过两个文档的diff生成Patch:
original={"a":1,"b":2,"c":[1,2,3]}target={"a":1,"b":3,"c":[1,4]}# 生成diff patchpatch=jsonpatch.make_patch(original,target)# 反向Patchreverse_patch=patch.reverse# 撤销修改reverted=reverse_patch.apply(target)当patch操作无效(如路径不存在、类型不匹配)时,会抛出JsonPatchException或JsonPointerException:
importjsonpatchfromjsonpatchimportJsonPatchExceptionfromjsonpointerimportJsonPointerException original={"a":1}patch=[{"op":"replace","path":"/non_existent","value":2}]try:result=jsonpatch.apply_patch(original,patch)exceptJsonPointerExceptionase:print("路径错误:",e)# 路径不存在exceptJsonPatchExceptionase:print("Patch错误:",e)# 操作无效集成Flask
fromflaskimportFlask,request,jsonifyimportjsonpatch app=Flask(__name__)# 模拟数据库中的资源data={"id":1,"name":"Product","price":100}@app.route("/products/1",methods=["PATCH"])defupdate_product():patch=request.json# 客户端发送的patch数组try:globaldata data=jsonpatch.apply_patch(data,patch)returnjsonify(data),200exceptExceptionase:returnjsonify({"error":str(e)}),400if__name__=="__main__":app.run(debug=True)注意事项
- 数组路径:
/users/-表示向数组末尾添加元素,/users/0表示第一个元素; - 原子性:
test操作可用于验证前置条件(如版本号),确保patch仅在数据未被修改时执行; - 性能:对于超大JSON文档,建议使用流式处理或分段
patch,避免内存占用过高。