本文正在參加「Python主題月」,詳情查看 活動連接python
微信公衆號搜索【程序媛小莊】,Rest cannot be enjoyed by lazy people~git
JSON使用的越多就越可能遇到JSON編碼或者解碼的瓶頸,Python的內置json庫雖然也很好用可是也有不少其餘更快的JSON庫可使用,可是具體選擇哪個或者哪種須要根據具體狀況,沒有一種標準的規則衡量哪種JSON最好或者最快,由於不一樣的項目有不一樣的需求,有的注重安全有的注重速度更快,本文介紹更快的json-orjson。github
orjson
是一個更加快速的Python JSON庫,經過基準測試發現比標準json庫和rapidjson
的速度更快,能夠序列化dataclass datetime numpy UUID
,json或者rapidjson
相比orjson
序列化獲得的結果是bytes
類型而不是json格式的str類型
,序列化時不會將unicode
轉換成ASCII
,須要注意的是,orjson
不提供dump/load
方法實現對file-like
對象進行序列化和反序列化。更多關於orjson
的使用請參考官方文檔。web
下面是json rapidjson orjson
進行的基準測試代碼以及結果。json
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
,須要根據實際狀況進行選擇哦~:api
json 1.1019978523254395
rapidjson 0.25800156593322754
orjson 0.0859987735748291
複製代碼
orjson
安裝安裝命令很是簡單:pip install orjson
瀏覽器
須要注意的是,在Linux環境中使用pip
命令安裝時pip
版本須要大於19.3,所以在安裝orjson
時能夠先更新pip
版本。安全
orjson
基本使用和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
方法將bytes類型的JSON格式數據反序列化稱爲Python示例對象。markdown
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"))
複製代碼
文章首發於微信公衆號程序媛小莊,同步於掘金。
碼字不易,轉載請說明出處,走過路過的小夥伴們伸出可愛的小指頭點個贊再走吧(╹▽╹)