Python对JSON非常友好,很多时候dict类型在形式上看起来就是JSON,而内置的json库通过loads()
和dumps()
两组方法恰当好处地将两者合二为一,以至于绝大多数时候没有必要去考虑引入一个新的方式来处理JSON。当然,Python社区是不会满足于大多数情况的,本文将从大多数情况的使用开始介绍一下Python中各种优秀的JSON工具库。
json是Python内置标准库,开箱即用。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
以下是Python 类型与JSON 类型的转化对照,注意json 库无法直接处理datetime, Decimal, UUID 等常用内建类型以及自定义类对象。
Python 类型 | JSON 类型 |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True / False | true / false |
None | null |
#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)
print(loaded["age"]) # 30
注意json 库处理超大 JSON 文件时(如 GB 级),json.load() 会一次性读取内存,效率低甚至崩溃。
进阶使用
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, indent=None, sort_keys=False)
具体参数说明:
参数名 | 说明 |
---|---|
indent=2 | 美化输出(缩进) |
sort_keys=True | 字典按 key 排序输出 |
ensure_ascii=False | 输出非 ASCII 字符(如中文) |
default=function | 自定义无法序列化对象的处理方式 |
from datetime import datetime
class User:
def __init__(self, name):
self.name = name
self.created = datetime.now()
u = User("Alice")
def encode_user(obj):
if isinstance(obj, User):
return {"name": obj.name, "created": obj.created.isoformat()}
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError("Not serializable")
print(json.dumps(u, default=encode_user, indent=2))
simplejson 是 Python 的一个第三方 JSON 库,是标准库 json 的超集,提供更强大的功能与兼容性。它最初就是标准库 json 的前身,所以用法非常相似,但提供了更多扩展选项(如精度控制、Decimal 支持、自定义编码等)。
安装
pip install simplejson
基本使用
simplejson也包含了loads\load
,dumps\dump
两组序列化(编码)、反序列化(解码)方法,且使用方法与内置的json库一模一样,在此不再赘述。
进阶使用
使用 Decimal 类型,simplejson支持Decimal类型的序列化与反序列化:
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(type(parsed['price'])) #
使用参数,simplejson中支持更加灵活的参数配置:
json.dumps(obj,
skipkeys=False,
ensure_ascii=True,
check_circular=True,
allow_nan=True,
cls=None,
indent=None,
separators=None,
default=None,
use_decimal=True,
namedtuple_as_object=True,
tuple_as_array=True,
bigint_as_string=False,
sort_keys=False
)
自定义对象序列化,如果对象实现了 .for_json()
方法,simplejson 会自动调用它:
class User:
def __init__(self, name):
self.name = name
def for_json(self):
return {'user': self.name}
user = User("Alice")
print(json.dumps(user)) # {"user": "Alice"}
对于高性能玩家来说,Python社区中主要有orjson、ujson与rapidjson三大性能库。其中orjson使用Rust实现,使用了 SIMD 和零拷贝,专为性能而生;ujson则是C 实现,主打轻量级;而rapidjson基于C++ 实现,属于功能和性能的平衡型选手。下面是三大性能库的具体使用PK。
我们基于下列代码对orjson、ujson与rapidjson进行了性能测试,
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)
基于 10 万条数据的序列化(dumps)和反序列化(loads)性能测试结果(单位:秒,越低越好),大致可以得到一个这样的结果:
库名 | 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都保持了json库的简洁:
# orjson
import orjson
orjson.dumps({'x': 1}) # → b'{"x":1}'
orjson.loads(b'{"x":1}') # → {'x': 1}
# ujson
import ujson
ujson.dumps({'x': 1}) # → '{"x":1}'
ujson.loads('{"x":1}') # → {'x': 1}
# rapidjson
import rapidjson
rapidjson.dumps({'x': 1}) # → '{"x":1}'
rapidjson.loads('{"x":1}') # → {'x': 1}
当然,在细节上它们仍有以下区别:
用法 | 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 |
总体而言,对于高性能玩家来说orjson是一个不错的选择,它有着比json标准库更好的性能,同时也支持更多的高级类型。