前言
JSON使用的越多就越可能遇到JSON编码或者解码的瓶颈,Python的内置json库虽然也很好用但是也有很多其他更快的JSON库可以使用,但是具体选择哪一个或者哪一种需要根据具体情况,没有一种标准的规则衡量哪一种JSON最好或者最快,因为不同的项目有不同的需求,有的注重安全有的注重速度更快,本文介绍更快的json-orjson。
orjson简介
orjson
是一个更加快速的Python JSON库,通过基准测试发现比标准json库和rapidjson
的速度更快,可以序列化dataclass datetime numpy UUID
,json或者rapidjson
相比orjson
序列化得到的结果是bytes
类型而不是json格式的str类型
,序列化时不会将unicode
转换成ASCII
,需要注意的是,orjson
不提供dump/load
方法实现对file-like
对象进行序列化和反序列化。更多关于orjson
的使用请参考官方文档。
json rapidson和orjson速度对比
下面是json rapidjson orjson
进行的基准测试代码以及结果。
import json
import orjson
import rapidjson
import time
m = {
"timestamp": 1556283673.1523004,
"task_uuid": "0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7",
"task_level": [1, 2, 1],
"action_status": "started",
"action_type": "main",
"key": "value",
"another_key": 123,
"and_another": ["a", "b"],
}
def benchmark(module_name, dumps):
start = time.time()
for i in range(100000):
dumps(m)
print(module_name, time.time() - start)
benchmark('json', json.dumps)
benchmark('rapidjson', rapidjson.dumps)
benchmark("orjson", lambda s: str(orjson.dumps(s), "utf-8")) # orjson只能输出bytes
并且结果如下,orjson
即使需要额外的Unicode解码也是最快的,但是并不代表博主一定推荐您使用orjson
,需要根据实际情况进行选择哦~:
json 1.1019978523254395
rapidjson 0.25800156593322754
orjson 0.0859987735748291
orjson基本使用
orjson
安装
安装命令非常简单:pip install orjson
需要注意的是,在Linux环境中使用pip
命令安装时pip
版本需要大于19.3,因此在安装orjson
时可以先更新pip
版本。
orjson
基本使用
序列化-dumps
和Python标准JSON库json
相比最大的不同在于orjson.dumps
返回的结果的是bytes
而json.dumps
返回的结果是str
。sort_keys
参数被option=orjson.OPT_SORT_KEYS
代替,indent
参数被option=orjson.OPT_INDENT_2
代替并且不支持其他indent
等级。
def dumps(
__obj: Any,
default: Optional[Callable[[Any], Any]] = ...,
option: Optional[int] = ...,
) -> bytes: ...
# 序列化
import orjson
m = {
"timestamp": 1556283673.1523004,
"task_uuid": "0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7",
"task_level": [1, 2, 1],
"action_status": "started",
"action_type": "哈哈",
"key": "value",
"another_key": 123,
"and_another": ["a", "b"],
}
res = orjson.dumps(m)
print(res)
# b'{"timestamp":1556283673.1523004,"task_uuid":"0ed1a1c3-050c-4fb9-9426-a7e72d0acfc7","task_level":[1,2,1],"action_status":"started","action_type":"\xe5\x93\x88\xe5\x93\x88","key":"value","another_key":123,"and_another":["a","b"]}'
反序列化-loads
loads
方法将bytes类型的JSON格式数据反序列化称为Python示例对象。
print(orjson.loads(res))
复制代码
float int str
类型的序列化和反序列化
float
orjson
在序列化和反序列化双精度浮点数时不会损失精度,在json rapidjson
中同样不会损失精度。orjson.dumps
对序列化Nan,Infinity,-Infinity
不兼容,会得到null
的结果,但是json和rapidjson
支持。
>>> import orjson, ujson, rapidjson, json
>>> orjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
b'[null,null,null]'
>>> rapidjson.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN,Infinity,-Infinity]'
>>> json.dumps([float("NaN"), float("Infinity"), float("-Infinity")])
'[NaN, Infinity, -Infinity]'
int
orjson
默认可以序列化和反序列化64-bits的证书,支持的范围是带符号的最小值(-9223372036854775807)到无符号的最大值(18446744073709551615),但是在某些场景下只支持53-bits的证书,比如web浏览器,对于不兼容的部分,dumps
方法会抛出JSONEncodeError
异常。
>>> import orjson
>>> orjson.dumps(9007199254740992)
b'9007199254740992'
>>> orjson.dumps(9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
>>> orjson.dumps(-9007199254740992, option=orjson.OPT_STRICT_INTEGER)
JSONEncodeError: Integer exceeds 53-bit range
str
orjson
和UTF8具有严格的一致性,比Python的标准库json
更为严格,json
在序列化和反序列化时使用UTF-16进行代理,但是这是不可用的UTF8。如果orjson.dumps
的参数传了一个不是UTF8的字符那么会抛出orjson.JSONEncodeError
异常,如果orjson.loads()
的参数收到了不可用的UTF8字符也会抛出同样的异常。
orjson和rapidjson
和Python标准库json
相比来说,对于不符合规则的输入始终都会抛出相应的异常。
为了程序的健壮性,可以在反序列化时先将bytes
类型编码成成UTF8格式。
>>> import orjson
>>> orjson.loads(b'"\xed\xa0\x80"')
JSONDecodeError: str is not valid UTF-8: surrogates not allowed
>>> orjson.loads(b'"\xed\xa0\x80"'.decode("utf-8", "replace"))
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!