python orjson
## Python orjson一个顺手的高速 JSON 解析库刚接触Python那会儿处理JSON基本上就是json模块一条路走到黑。后来项目规模上来了数据量一涨json.loads和json.dumps那点性能瓶颈就藏不住了。有人开始用simplejson有人用ujson不过最近几年越来越多的生产环境里出现了orjson的身影。这东西其实是个用Rust写的JSON库核心逻辑用Rust实现通过Python的C扩展接口暴露给上层调用。为什么选Rust因为它能在保证内存安全的前提下把JSON解析和序列化的速度推到极致。简单说orjson就是个更快、更省内存的JSON处理工具而且数据越复杂优势越明显。它到底能干什么日常用的JSON操作orjson都覆盖了。解析字符串、序列化对象这些基础能力跟标准json模块别无二致。但有几个地方确实让json模块望尘莫及第一处理大JSON文件时orjson的按需解析是个好东西。有时候我们只需要响应体里那一小段数据orjson可以选择性地解析特定字段而不是把整个JSON结构全塞进内存。这就好比翻一本厚厚的黄页你是想一页一页全看完还是只查那个具体的电话号码第二对日期时间的原生支持。标准库里的json模块碰到datetime对象直接抛TypeError得自己写encoder。orjson倒好它能直接把datetime序列化成ISO 8601格式的字符串。这个特性在写API接口的时候特别省心。第三bytes类型的序列化。Python的json模块对bytes是束手无策的但orjson能把它序列化成UTF-8编码的字符串。如果你的应用里经常跟二进制数据打交道这个细节能省掉不少编码解码的麻烦事。怎么用起来安装很简单pip install orjson就行。用法也基本是照着json模块的API风格来的上手几乎没有学习成本importorjson# 解析JSON字符串data{name: 张三, age: 30}parsedorjson.loads(data)# 序列化成JSON字符串outputorjson.dumps({name:李四,age:25})# 注意这里返回的是bytes类型不是strprint(output)# b{name:李四,age:25}有个小细节需要注意orjson.dumps默认返回bytes而不是str。要想拿到字符串可以这样resultorjson.dumps(obj).decode(utf-8)其实这就是个设计哲学问题。orjson的作者认为JSON数据在网络传输和文件存储中本就是UTF-8的形式bytes才是最原始的表示。如果你写web应用bytes直接给响应体比str转bytes更快。处理可选参数的时候orjson用option常量来控制行为而不是像json模块那样靠一个个bool参数堆data{name:赵六,created_at:datetime.now()}# 序列化datetime对象outputorjson.dumps(data,optionorjson.OPT_OMIT_MICROSECONDS|orjson.OPT_UTC_Z)# 排序键名outputorjson.dumps(data,optionorjson.OPT_SORT_KEYS)这个option的设计值得玩味。用位运算的方式组合多个选项虽然一开始看着不习惯但用久了发现比给函数传一堆命名参数要灵活特别是组合选项的时候。怎么用好它不是所有场景都需要上orjson。如果你的应用每次只处理几个KB的小JSON拿json模块对付一下也差不了多少。但一旦遇到高频率、大数据的JSON操作orjson的优势就淋漓尽致了。举个实在的例子一个日志收集系统每天要处理上亿条JSON格式的日志条目。这个时候哪怕每条记录省下零点几毫秒累积下来的性能提升都是可观的。而且orjson往往能省出30%到50%的CPU开销这个在生产环境里可能意味着少用几台服务器。一个老生常谈但依然要提的别在性能瓶颈出现之前盲目优化。先把代码写清楚跑对了然后用性能分析工具定位真正的瓶颈在哪里。如果发现JSON解析占了很大比重再用orjson替换也不迟。这个替换成本很低基本上改一行import就行。处理敏感信息的时候要注意orjson默认会把非ASCII字符做转义。如果接口需要返回中文却看到一堆转义字符那就需要关闭OPT_ESC_FORWARD_SLASH或者自定义encoder。其实这个转义行为是JSON规范里允许的但有些前端框架或者下游服务不一定认这个。和同类技术掰掰手腕标准库的json模块自然不必多说纯Python实现没什么性能可言。但它胜在最稳定、最兼容是调试阶段的好伙伴。simplejson其实跟json模块一脉相承算是对标准库的补充。它支持更多JSON规范里的细节比如无限递归检测、自定义对象的serialization。不过性能上simplejson跟orjson比还是有差距的大概是两倍不到的差距。ujsonUltraJSON也算是个老牌选手了。它用C语言实现速度比json模块快不少。但有一个致命的短板它对数据的严格性要求比较低有时候会悄无声息地吞掉一些问题数据。比如一个非法的UTF-8字符ujson可能就默默处理了orjson会直接抛异常。这个取舍让orjson在生产环境里更有竞争力。还有一个叫python-rapidjson的库底层用的是RapidJSON这个C库。性能也算不错不过跟orjson比起来在处理重复字段、多个空格这类边缘情况时orjson表现得更加谨慎和可靠。说到底orjson胜在两点速度快而且快得稳定数据类型支持完善能省掉很多手动转换的麻烦。如果非要说缺点大概就是它对JSON的严格程度比较高碰到不符合规范的数据就不客气地抛异常这在处理不可控的外部数据源时需要注意。不过话说回来对数据的严格检查本身也是好事。与其让问题数据悄无声息地通过不如尽早发现并处理。