Python中的JSON工具库
1、原生json库
json是Python内置标准库,开箱即用。json库也非常简单,就两组序列化(编码)、反序列化(解码)方法。
基本使用
1)Python对象与JSON字符串的互相转化:
import json
data = {"name": "Alice", "age": 30, "is_active": True}
# json.dumps将 Python 对象转为 JSON 字符串
json_str = json.dumps(data)
print(json_str) # {"name": "Alice", "age": 30, "is_active": true}
# json.loads将JSON 字符串转为 Python 对象
parsed = json.loads(json_str)
print(parsed) # {"name": "Alice", "age": 30, "is_active": true}
以下是Python 类型与JSON 类型的转化对照,注意json 库无法直接处理datetime, Decimal, UUID 等常用内建类型以及自定义类对象。
| Python 类型 | JSON 类型 |
| dict | object |
| list, tuple | array |
| str | number |
| True / False | true / false |
| None | null |
2)JSON文件的读取与写入:
#json.dump写入 JSON 到文件
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2)
#json.load从文件读取 JSON
with open('data.json', 'r', encoding='utf-8') as f:
loaded = json.load(f)
注意json 库处理超大 JSON 文件时(如 GB 级),json.load() 会一次性读取内存,效率低甚至崩溃。
具体参数说明:
| 参数名 | 说明 |
| indent=2 | 美化输出(缩进) |
| sort_keys=True | 字典按 key 排序输出 |
| ensure_ascii=False | 输出非 ASCII 字符(如中文) |
| default=function | 自定义无法序列化对象的处理方式 |
2、simplejson
simplejson 是 Python 的一个第三方 JSON 库,是标准库 json 的超集,提供更强大的功能与兼容性。它最初就是标准库 json 的前身,所以用法非常相似,但提供了更多扩展选项(如精度控制、Decimal 支持、自定义编码等)
安装
pip install simplejson
基本使用
simplejson也包含了loads\load,dumps\dump两组序列化(编码)、反序列化(解码)方法,且使用方法与内置的json库一模一样。
import simplejson as json
data = {"name": "Alice", "age": 30, "is_active": True}
# json.dumps将 Python 对象转为 JSON 字符串
json_str = json.dumps(data)
print(json_str) # {"name": "Alice", "age": 30, "is_active": true}
# json.loads将JSON 字符串转为 Python 对象
parsed = json.loads(json_str)
print(parsed) # {"name": "Alice", "age": 30, "is_active": true}
使用 Decimal 类型,simplejson支持Decimal类型的序列化与反序列化:
import simplejson as json
from decimal import Decimal
data = {'price': Decimal('19.99')}
# 支持 Decimal(不会强制转 float)
json_str = json.dumps(data, use_decimal=True)
print(json_str) # {"price": 19.99}
# 正确解析为 Decimal
parsed = json.loads(json_str, use_decimal=True)
print(parsed) # {'price': Decimal('19.99')}
3、orjson、ujson与rapidjson
安装
pip install orjson pip install ujson pip install python-rapidjson
orjson用法:
import orjson
data = {"name": "Alice", "age": 30, "is_active": True}
# json.dumps将 Python 对象转为 JSON 字符串
json_str = orjson.dumps(data)
print(json_str) # b'{"name":"Alice","age":30,"is_active":true}'
# json.loads将JSON 字符串转为 Python 对象
parsed = orjson.loads(json_str)
print(parsed) #{'name': 'Alice', 'age': 30, 'is_active': True}
ujson用法:
import ujson
data = {"name": "Alice", "age": 30, "is_active": True}
# json.dumps将 Python 对象转为 JSON 字符串
json_str = ujson.dumps(data)
print(json_str) # {"name":"Alice","age":30,"is_active":true}
# json.loads将JSON 字符串转为 Python 对象
parsed = ujson.loads(json_str)
print(parsed) # {'name': 'Alice', 'age': 30, 'is_active': True}
rapidjson用法:
import rapidjson
data = {"name": "Alice", "age": 30, "is_active": True}
# json.dumps将 Python 对象转为 JSON 字符串
json_str = rapidjson.dumps(data)
print(json_str) # {"name":"Alice","age":30,"is_active":true}
# json.loads将JSON 字符串转为 Python 对象
parsed = rapidjson.loads(json_str)
print(parsed) # {'name': 'Alice', 'age': 30, 'is_active': True}
orjson、ujson、rapidjson与json区别:
import orjson, ujson, rapidjson, json
import time
data = [{"id": i, "name": f"user{i}", "active": True, "score": i * 0.5} for i in range(100000)]
def test(lib, dumps_func, loads_func):
t1 = time.time()
s = dumps_func(data)
t2 = time.time()
obj = loads_func(s)
t3 = time.time()
print(f"{lib}: dumps={t2 - t1:.4f}s, loads={t3 - t2:.4f}s")
test("orjson", orjson.dumps, orjson.loads)
test("ujson", ujson.dumps, ujson.loads)
test("rapidjson", rapidjson.dumps, rapidjson.loads)
test("json", json.dumps, json.loads)
性能结果区别:
orjson: dumps=0.0150s, loads=0.0319s ujson: dumps=0.0539s, loads=0.0578s rapidjson: dumps=0.0598s, loads=0.1167s json: dumps=0.0997s, loads=0.0768s
| 库名 | dumps 时间 | loads 时间 | 总体性能评价 |
|---|---|---|---|
| orjson | 🥇 最快(~0.09s) | 🥇 最快(~0.08s) | 🚀🚀🚀 超高速 |
| ujson | 次快(~0.13s) | 次快(~0.12s) | 🚀🚀 快 |
| rapidjson | 稍慢(~0.18s) | 稳定(~0.15s) | 🚀 中等 |
| json(内置) | 🐢 ~0.27s | 🐢 ~0.23s | 🐢 慢 |
功能结果区别:
| 用法 | orjson | ujson | rapidjson |
|---|---|---|---|
| 序列化 | orjson.dumps(data) → bytes | ujson.dumps(data) → str | rapidjson.dumps(data) → str |
| 反序列化 | orjson.loads(bytes/str) | ujson.loads(str) | rapidjson.loads(str) |
| 注意点 | 返回 bytes,需 .decode() | 无 datetime 支持 | 返回 str,兼容性强 |
| 功能特性 | orjson | ujson | rapidjson |
|---|---|---|---|
| ✅ 支持 datetime | ✅ ISO 格式 | ❌ | ✅ 可配置格式 |
| ✅ 支持 Decimal | ⚠️ 转为 float | ❌ | ✅ 原生支持 |
| ✅ 自定义对象序列化 | ✅ 支持 default | ❌ | ✅ 支持 default |
| ✅ 精度控制(float、NaN) | ✅ option= 参数 | ❌ | ✅ 多选项支持 |
| ✅ 缩进与格式化输出 | ✅(有) | ❌ | ✅ indent 参数 |
| ✅ 输出类型 | bytes | str | str |
4、json5
json5 是 JSON 的超集,允许更宽松的语法(如允许注释、单引号、不加引号的键等),适合人类书写配置文件。json5 库提供了对 JSON5 格式的解析支持。
pip install json5
import json5
# JSON5 字符串,包含注释、单引号、不加引号的键等
json5_str = """
{
// 这是一个注释
unquotedKey: 'value',
"quotedKey": 123,
trailingComma: true,
}
"""
# 解析 JSON5 字符串
data_loads = json5.loads(json5_str)
print(data_loads)
data_dumps = json5.dumps(json5_str)
print(data_dumps)
json5 库支持的扩展语法解析:
| 特性 | 说明 |
|---|---|
| 注释 | 支持 // 单行注释 和 /* */ 多行注释 |
| 尾逗号 | 允许最后一个元素后写逗号 |
| 单引号字符串 | 'text' 与 "text" 都合法 |
| 未加引号的键 | 允许键名不加引号(如 foo: 1) |
| 十六进制数字 | 支持 0x1234 数字表示 |
| 正负号数字 | 支持 +1、-2 |
| 多行字符串 | 可以使用 \ 跨行字符串 |
| 数字中的下划线 | 如 1_000_000(提高可读性)
|
写入 JSON5 数据
虽然 json5 支持读取 JSON5 文件,但并不支持将 Python 对象序列化为 JSON5 格式(即没有 json5.dumps() 带有 JSON5 特性的输出功能)。它只能写成标准 JSON
5、dataclasses_json
dtaclasses-json主要用于dataclasses 的 JSON 序列化/反序列化,它还支持dataclasses与dict类型的互相转化, 是 dataclasses 的一个强力补丁库。pip install dataclasses-json
基本使用
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class User:
id: int
name: str
user = User(id=1, name='Alice')
# 序列化为 JSON 字符串
json_str = user.to_json()
print(json_str) # {"id": 1, "name": "Alice"}
# 反序列化为 Python 对象
new_user = User.from_json('{"id": 2, "name": "Bob"}')
print(new_user.name) # Bob
# 转为字典
print(user.to_dict()) # {'id': 1, 'name': 'Alice'}
# 从字典创建
u = User.from_dict({'id': 3, 'name': 'Carol'})
print(u) # User(id=3, name='Carol')
嵌套结构支持
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class Address:
city: str
zipcode: str
@dataclass_json
@dataclass
class Person:
name: str
address: Address
p = Person(name='Tom', address=Address(city='NY', zipcode='10001'))
print(p.to_json())
# {"name": "Tom", "address": {"city": "NY", "zipcode": "10001"}}
# 自动反序列化嵌套结构
data = Person.from_json('{"name": "Amy", "address": {"city": "LA", "zipcode": "90001"}}')
print(data)
# Person(name='Amy', address=Address(city='LA', zipcode='90001'))
转换配置config函数可以用于配置字段的类型和别名等。
from dataclasses import dataclass
from dataclasses_json import dataclass_json
import datetime
@dataclass_json
@dataclass
class Data:
user_id: int = config(field_name='userId')
time: datetime = config(
encoder=datetime.isoformat,
decoder=datetime.fromisoformat,
mm_field=fields.DateTime()
)
d = Data(user_id=1001, time=datetime(2024, 1, 1, 12, 0))
6、JSON数据校验
6.1 jsonschema
jsonschema 是 Python 中用于JSON 数据结构验证的官方实现之一,遵循 JSON Schema 标准,可以验证 JSON 数据是否符合你定义的“规则/结构”。
pip install jsonschema
基本使用
from jsonschema import validate
from jsonschema.exceptions import ValidationError
# 定义 JSON Schema(结构规则)
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0},
},
"required": ["name", "age"]
}
# 要校验的 JSON 数据
data = {
"name": "Alice",
"age": 30
}
try:
validate({"name": "Bob"}, schema)
except ValidationError as e:
print("校验失败:", e.message)
常见规则示例
{
"type": "object",
"properties": {
"username": {"type": "string", "minLength": 3, "pattern": "^[a-zA-Z0-9_]+$"},
"age": {"type": "integer", "minimum": 0, "maximum": 120},
"email": {"type": "string", "format": "email"},
"tags": {
"type": "array",
"items": {"type": "string"},
"maxItems": 5
},
"active": {"type": "boolean"}
},
"required": ["username", "email"]
}
自定义规则示例
from jsonschema import Draft7Validator, FormatChecker
schema = {
"type": "object",
"properties": {
"phone": {"type": "string", "format": "phone"}
}
}
# 添加自定义格式检查器
@FormatChecker.cls_checks("phone")
def is_phone(value):
import re
return bool(re.match(r'^\d{11}$', value))
data = {"phone": "13800138000"}
6.2 pydantic
Pydantic 是 Python 中最流行的数据验证和数据模型库,它的功能完全有必要另开一篇文章来详细讨论,这里仅仅介绍一下它在JSON 数据校验中的使用。
pip install pydantic
基本使用
from pydantic import Field
class Product(BaseModel):
name: str = Field(..., min_length=3)
price: float = Field(..., gt=0, lt=10000)
# 自动校验 JSON 字段
try:
Product.model_validate({"name": "P", "price": -10})
except ValidationError as e:
数组与复杂结构
from typing import List
class Tag(BaseModel):
name: str
class Post(BaseModel):
title: str
tags: List[Tag]
post_data = {
"title": "My Post",
"tags": [{"name": "Python"}, {"name": "FastAPI"}]
}
post = Post.model_validate(post_data)
自定义校验器
from pydantic import field_validator
class User(BaseModel):
username: str
@field_validator('username')
def no_spaces(cls, v):
if ' ' in v:
raise ValueError("username can't contain spaces")
6.3 Voluptuous
Voluptuous 是一个用于 Python 数据校验的库,语法灵活、结构清晰,不同于jsonschema 所遵循JSON Schema 标准,它采用的是「函数式」「声明式」风格。
from voluptuous import Schema, Required, All, Length, Range, MultipleInvalid
schema = Schema({
Required('name'): All(str, Length(min=2)),
Required('age'): All(int, Range(min=0, max=120)),
'email': str,
})
data = {
'name': 'Alice',
'age': 30,
'email': 'alice@example.com'
}
try:
schema({'name': 'A', 'age': -1})
except MultipleInvalid as e:
print(e)
常用的构造器和校验器主要有:
| 校验器 | 功能 |
|---|---|
| Required(...) | 必须字段 |
| Optional(...) | 可选字段 |
| All(...) | 多重条件组合校验器 |
| Length(min, max) | 字符串或列表长度限制 |
| Range(min, max) | 数值范围限制 |
| Match(r'^\w+$') | 正则匹配 |
| In([...]) | 枚举(值必须属于其中之一) |
| Any(A, B) | 多个类型之一 |
| [type] | 列表中每一项的类型 |
| {str: int} | 键值类型均为特定类型的 dict |
嵌套结构与数组校验
config_schema = Schema({
Required('host'): str,
Required('port'): All(int, Range(min=1024, max=65535)),
'debug': bool,
'users': [{
Required('name'): str,
'email': str
}]
})
config = {
'host': 'localhost',
'port': 8000,
'debug': True,
'users': [{'name': 'admin', 'email': 'admin@example.com'}]
}
自定义验证规则
from voluptuous import Invalid
def is_even(v):
if v % 2 != 0:
raise Invalid("必须为偶数")
return v
schema = Schema({'number': is_even})
print(schema({'number': 4}))
7、JSON数据的比较
7.1、jsondiff
jsondiff 是一个用于比较两个 JSON(或 Python 字典)对象差异的轻量级库。它能生成最小的变更(patch)表示,并支持将差异反向应用和还原原始数据。pip install jsondiff
基本用法
import jsondiff
a = {"name": "Alice", "age": 30}
b = {"name": "Alice", "age": 31}
diff = jsondiff.diff(a, b)
print(diff) # 输出:{'age': 31}
合并与还原(补丁 patch)
import jsondiff
a = {"name": "Alice", "age": 30}
b = {"name": "Alice", "age": 31}
diff = jsondiff.diff(a, b)
print(diff) # 输出:{'age': 31}
patch = jsondiff.diff(a, b)
new_obj = jsondiff.patch(a, patch) # 应用 patch 得到 b
original = jsondiff.unpatch(new_obj, patch) # 还原为 a
print(new_obj) # {'name': 'Alice', 'age': 31}
print(original) # {'name': 'Alice', 'age': 30}
嵌套结构 diff
x = {"user": {"name": "Alice", "tags": ["a", "b"]}}
y = {"user": {"name": "Alice", "tags": ["a", "c"]}}
print(jsondiff.diff(x, y))
参数选项(比如忽略顺序)
a = {'numbers': [1, 2, 3]}
b = {'numbers': [3, 2, 1]}
# 默认考虑顺序
print(jsondiff.diff(a, b))
# 忽略顺序
print(jsondiff.diff(a, b, dump=True, syntax='symmetric', sequence_matcher=jsondiff.SequenceMatcher))
7.2、deepdiff
比起jsondiff,deepdiff 的功能更加强大,尤其用于深度比较两个 Python 对象(特别是嵌套的 dict、list、set、tuple 等),并提供结构化的差异信息。
pip install deepdiff
from deepdiff import DeepDiff
a = {"name": "Alice", "age": 30}
b = {"name": "Alice", "age": 31}
diff = DeepDiff(a, b)
print(diff)
差异信息说明:
| 键名 | 含义 |
|---|---|
| values_changed | 值发生了变化 |
| type_changes | 类型发生变化 |
| dictionary_item_added | 新增键 |
| dictionary_item_removed | 删除键 |
| iterable_item_added | 列表/集合等新增项 |
| iterable_item_removed | 列表/集合等移除项 |
| attribute_changed | 对象属性变更(如类实例) |
|
set_item_removed/set_item_added |
集合元素变更 |
生成和应用补丁
from deepdiff import DeepDiff, patch, unpatch
a = {"x": 1}
b = {"x": 2}
ddiff = DeepDiff(a, b, view='tree')
p = ddiff.patch
# 应用 patch
new_data = patch(a, p)
print(new_data) # {'x': 2}
# 还原
orig = unpatch(new_data, p)
print(orig )
差异路径与提取值
ddiff = DeepDiff(a, b, view='tree')
for diff_item in ddiff['values_changed']:
print(diff_item.path(), diff_item.t1, "→", diff_item.t2)
嵌套结构 diff
a = {"user": {"name": "Alice", "roles": ["admin", "dev"]}}
b = {"user": {"name": "Alice", "roles": ["admin", "ops"]}}
diff = DeepDiff(a, b)
参数选项(比如忽略顺序,设置精度)
a = {'numbers': [1, 2, 3]}
b = {'numbers': [3, 2, 1]}
diff = DeepDiff(a, b, ignore_order=True)
print(diff) # 无差异
# 浮点精度控制
diff = DeepDiff(0.3000000001, 0.3, significant_digits=7)
8、JSON数据的查询与操作
8.1 pyjq
pyjq 封装了 jq命令行工具,可以通过jq 表达式对 JSON 数据进行强大的模式匹配与提取、转换等操作。
pip install pyjq
import pyjq
data = {
"users": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
]
}
result = pyjq.all('.users[] | select(.age > 26) | .name', data)
常用的jq 表达式:
| 表达式 | 含义 |
|---|---|
| . | 原始对象本身 |
| .field | 提取字段 |
| .[] | 遍历数组 |
| select(.field > 10) | 条件筛选 |
| map(.field) | 映射数组中每一项的某字段 |
| .{a: .field1, b: .field2} | 构造新字典 |
| `.[] | {name, age}` |
嵌套结构
data = {
"items": [
{"id": 1, "tags": ["a", "b"]},
{"id": 2, "tags": ["b", "c"]}
]
}
# 提取所有 tags
result = pyjq.all('.items[].tags[]', data)
提取字典转为新结构
data = {
"name": "Alice",
"profile": {
"email": "a@example.com",
"phone": "123456"
}
}
result = pyjq.first('{username: .name, contact: .profile.email}', data)
8.2 jsonpath-ng
jsonpath 是用于在 Python 中从 JSON 数据结构中提取数据的查询、操作工具,类似于 XPath 之于 XML。 jsonpath-ng(前身jsonpath)是 JSONPath 在 Python 中的主流实现库。
pip install jsonpath-ng
基本使用
from jsonpath_ng import jsonpath, parse
data = {
"store": {
"book": [
{"title": "Book A", "price": 8.95},
{"title": "Book B", "price": 12.99}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
# 编译 JSONPath 表达式
jsonpath_expr = parse('$.store.book[*].title')
# 执行匹配并提取结果
matches = jsonpath_expr.find(data)
titles = [match.value for match in matches]
常见的JSONPath 表达式:
| 表达式 | 说明 |
|---|---|
| $ | 根节点 |
| $.store.book | 访问键路径 |
| $.store.book[*].title | 遍历数组并提取字段 |
| $..price | 递归提取所有层级的 price |
| $.store.book[0] | 第一个数组元素 |
| $.store.book[-1:] | 最后一个元素 |
| $.store.book[?(@.price > 10)] | 条件筛选 |
条件查询
expr = parse('$.store.book[?(@.price > 10)].title')
matches = expr.find(data)
titles = [m.value for m in matches]
修改数据
可以通过 match.path.update(data, new_value) 来修改原始数据:
expr = parse('$.store.bicycle.color')
matches = expr.find(data)
for match in matches:
match.path.update(data, "blue")
print(data["store"]["bicycle"]["color"]) # blue
提取匹配路径和值
for match in expr.find(data):
print(match.path, match.value)
9、JSON数据文件的操作
9.1 ijson
ijson 是一个用于 增量解析 JSON 文件 的 Python 库,特别适用于 大文件/流式处理。它基于迭代器,可边读边解析,不会一次性加载整个 JSON,从而节省内存。
pip install ijson
基本用法
JSON数据源
{
"records": {
"item": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
}
import ijson
with open('large_file.json', 'r') as f:
for item in ijson.items(f, 'records.item'):
print(item)
# {'id': 1, 'name': 'Alice'}
读取嵌套数组结构
with open('large_file.json', 'r') as f:
for item in ijson.items(f, 'data.users.item'):
print(item)
从网络流/HTTP/Bytes 中读取
import requests
import ijson
response = requests.get('https://example.com/data.json', stream=True)
for item in ijson.items(response.raw, 'users.item'):
print(item)
9.2 jsonlines
jsonlines 是一种特殊格式的 JSON 文件,每行是一个合法的 JSON 对象,广泛用于日志、数据流、大规模数据处理(如机器学习训练集) 中。
pip install jsonlines
JSON数据源
{"id": 1, "name": "Alice"}
{"id": 2, "name": "Bob"}
读取 JSON Lines 文件
import jsonlines
with jsonlines.open('data.jsonl') as reader:
for obj in reader:
print(obj['name'])
写入 JSON Lines 文件
import jsonlines
data = [{"id": 1}, {"id": 2}, {"id": 3}]
with jsonlines.open('output.jsonl', mode='w') as writer:
writer.write_all(data)
9.3 jsonpickle
jsonpickle 是一个功能强大的 Python 库,用于将 复杂的 Python 对象(如自定义类、函数、日期、NumPy、Pandas 等)序列化为 JSON,并能将其反序列化回来,它支持更多内置类型与第三方类型。
pip install jsonpickle
序列化(encode)
import jsonpickle
class Person:
def __init__(self, name):
self.name = name
obj = Person("Alice")
# 序列化为 JSON 字符串
json_str = jsonpickle.encode(obj)
反序列化(decode)
obj_restored = jsonpickle.decode(json_str)
复杂类型
import jsonpickle
import datetime
import decimal
data = {
"time": datetime.datetime.now(),
"score": decimal.Decimal('9.99'),
"tags": {"a", "b", "c"},
}
json_str = jsonpickle.encode(data)
print(json_str)
restored = jsonpickle.decode(json_str)
保存和加载 JSON 文件
# 写入文件
with open('person.json', 'w') as f:
f.write(jsonpickle.encode(obj))
# 从文件读取
with open('person.json', 'r') as f:
obj2 = jsonpickle.decode(f.read())
自定义 JSON处理库
jsonpickle可以指定JSON的处理库,如选择高性能库orjson。
import jsonpickle.ext.orjson as orjson
jsonpickle.set_encoder_options('orjson', option=orjson.OPT_INDENT_2)

浙公网安备 33010602011771号