REST API 是 在全世界使用標(biāo)準(zhǔn)化的消息格式合呐。JSON 是互聯(lián)網(wǎng)上數(shù)據(jù)交換的基石,作為 JavaScript 的一個(gè)子集笙以,它從一開始就獲得了巨大的推廣淌实。它特別清晰易讀的語法也有利于推廣。
據(jù)我所知各種語言都有 JSON 庫用于序列化和反序列化猖腕。實(shí)際上在 Python 中就有很多種 JSON 庫拆祈。在下文中,我將為大家比較它們的異同倘感。
引用庫
CPython 本身具有一個(gè) json 模塊放坏。它最初是由 Bob Ippolito 作為 simplejson 開發(fā)的,并被合并到 Python 2.4 中(源代碼)老玛。CPython 遵循 Python 軟件基金會(huì)(Python Software Foundation)許可協(xié)議淤年。
simplejson 仍然作為一個(gè)單獨(dú)的庫存在钧敞,你可以通過 pip 安裝它。它是帶有可選 C 擴(kuò)展的純 Python 庫互亮。Simplejson 遵循 MIT 和 Academic Free License(AFL)許可協(xié)議犁享。
ujson 是對(duì) C 語言庫 Ultra JSON 的綁定。Ultra JSON 由 ESN(一家電子藝術(shù)工作室公司)開發(fā)豹休,并獲得了 3條款BSD許可炊昆。Ultra JSON 在 Github 上擁有 3k 星,305 個(gè) fork威根,50 個(gè)貢獻(xiàn)者凤巨,最近一次提交的日期只有 12 天,而最后一次提交是在 5 天之前發(fā)布的洛搀。我聽說它處于“維護(hù)模式”(來源)敢茁,表明沒有新的進(jìn)展。
pysimdjson 是對(duì) C ++ 庫 simdjson 的綁定留美。SIMDjson 從加拿大獲得資助彰檬。simdjson 在 Github 上有 12.2k 顆星,611 個(gè)分支谎砾,63 個(gè)貢獻(xiàn)者逢倍,最后一次提交是 11 小時(shí)前,而最后一個(gè) issue 是 2 小時(shí)前創(chuàng)建的景图。
python-rapidjson 是對(duì) C ++ 庫 RapidJSON 的綁定较雕。RapidJSON 由 騰訊 開發(fā)。RapidJSON 在 GitHub 上有 9.8k 個(gè)星挚币,2.7k 個(gè) fork亮蒋,150 個(gè)貢獻(xiàn)者,最近一次提交大約在 2 個(gè)月前妆毕,而最后一個(gè) issue 是 17 天前創(chuàng)建的慎玖。
orjson 是一個(gè) Python 軟件包,依靠 Rust 來完成繁重的工作设塔。
成熟度和操作安全性
上面所有提到的庫都可以毫無問題地用作 benchmark 示例凄吏,切換 JSON 模塊也不是什么大問題,但我仍然想確定相關(guān)模塊是否支持闰蛔。
CPython痕钢,simplejson,ujson 和 orjson 都認(rèn)為他們自己已經(jīng)可以投產(chǎn)了序六。
python-rapidjson 將自身標(biāo)記為 alpha任连,但是一位維護(hù)人員說這是一個(gè)錯(cuò)誤,并將很快得到修復(fù)(資源)例诀。
問題
判斷一個(gè)庫的問題是否能夠被順利解決随抠,一個(gè)直接的方式是直接去它的倉(cāng)庫創(chuàng)建 issue裁着,并觀察后續(xù)的跟進(jìn)反饋:
SimpleJSON:第二天我得到了答復(fù),回答很明確拱她,易于理解二驰,友善。Bob Ippolito 回答了我秉沼。他是最初開發(fā)這個(gè)庫的人桶雀,并且在 JSON 模塊的 Python 文檔中也提到了他!
uJSON:30分鐘內(nèi)唬复,我得到了一個(gè)清晰矗积,友好,易于遵循的答案敞咧。@hugovank
ORJSON:10天沒有反應(yīng)棘捣,然后關(guān)閉,沒有任何評(píng)論休建。
[PySIMDJSON]:15天后無人答復(fù)乍恐。
Python-RapidJSON:在30分鐘內(nèi),我得到了一個(gè)清晰测砂,友好禁熏,易于遵循的答案。十天后合并了一個(gè)簡(jiǎn)單的PR邑彪。
通過以上操作我得出一個(gè)答案,它們基本上沒有相互關(guān)系胧华。
基準(zhǔn)測(cè)試(Benchmark)
為了正確地對(duì)不同的庫進(jìn)行基準(zhǔn)測(cè)試寄症,我考慮了以下情況:
API:交換信息的 Web 服務(wù)。它可能包含 Unicode 并具有嵌套結(jié)構(gòu)矩动。Twitter API 的 JSON 文件聽起來不錯(cuò)有巧,可以對(duì)此進(jìn)行測(cè)試。
API JSON錯(cuò)誤:我很好奇如果 JSON API 格式有錯(cuò)誤悲没,性能會(huì)如何變化篮迎。因此,我在中間刪除了一個(gè)大括號(hào)示姿。
GeoJSON:我首先通過一個(gè)開源街道地圖導(dǎo)出器 Overpass Turbo 得到了 GeoJSON 格式的 JSON 文件甜橱。你將獲得瘋狂多的 JSON 文件,這些文件大多具有坐標(biāo)栈戳,而且還很嵌套岂傲。
機(jī)器學(xué)習(xí):只是大量的浮點(diǎn)數(shù)列表。這些可能是神經(jīng)網(wǎng)絡(luò)層的權(quán)重子檀。
JSON行:結(jié)構(gòu)化日志在行業(yè)中大量使用镊掖。如果分析這些日志乃戈,可能需要遍歷千兆字節(jié)的數(shù)據(jù)。它們都是帶有日期時(shí)間對(duì)象亩进、消息症虑、記錄器、日志狀態(tài)等信息的簡(jiǎn)單字集归薛。
反序列化速度
我將我的硬盤驅(qū)動(dòng)器的讀取速度設(shè)置了一個(gè)較低的上限谍憔,在以下3個(gè)圖表中將以它作為基準(zhǔn)。
由此得出的結(jié)論是:
Rapidjson 速度很慢苟翻,但是對(duì)于像 twitter.json 這樣的小型 JSON韵卤,你不會(huì)注意到有什么不同〕缑ǎ可以通過結(jié)構(gòu)化日志看到這一點(diǎn)沈条。
simdjson,orjson 和 ujson 都快得驚人诅炉。
對(duì)于大多數(shù)庫而言蜡歹,讀取包含結(jié)構(gòu)錯(cuò)誤的 JSON 文件的速度相同。一個(gè)值得注意的例外是 Rapidjson涕烧。我猜一旦發(fā)現(xiàn)錯(cuò)誤月而,它將中止讀取文件。
序列化速度
在這里议纯,我預(yù)先創(chuàng)建了 JSON 字符串,并以寫入磁盤的時(shí)間作為基線測(cè)量了所需的時(shí)間父款。
我由此得出的結(jié)論是:
orjson 非常快瞻凤,超級(jí)接近我的硬盤驅(qū)動(dòng)器寫入速度憨攒。ujson 也非常接近。
Rapidjson 也很快阀参,但與 orjson 或 ujson 不在同一級(jí)別肝集。
simdjson 很慢。
專業(yè)的 JSON 工作流
最后總結(jié)一下蛛壳,我想指出一些我之前看到并記錄下來的問題:
-
調(diào)用變量
foo_json
:JSON 是一種字符串格式杏瞻。如果不是字符串,則不是 JSON衙荐。如果使用bar = json.loads(foo)
反序列化 JSON捞挥,則 bar 不是 JSON。你可以將 bar 序列化為與 JSON
foo
等效的 JSON忧吟,但 bar 不是 JSON,這是一個(gè) Python 對(duì)象树肃,很像一個(gè)字典對(duì)象,就將它當(dāng)作foo_json
瀑罗。 屬性會(huì)在各處進(jìn)行檢查:如果你收到 JSON 數(shù)據(jù)胸嘴,很輕松就可以轉(zhuǎn)換為 Python 對(duì)象(例如字典)并使用它雏掠。這對(duì)于概念驗(yàn)證代碼或很小的 JSON 字符串來說是很好的選擇。如果你不將其轉(zhuǎn)換為 dataclass 之類的劣像,它將一團(tuán)糟乡话。
pydantic 是一個(gè)超級(jí)有用的驗(yàn)證庫。你可以使用自己喜歡的 JSON 庫將 JSON 字符串解析為帶有 字典/列表/字符串/數(shù)字/布爾值的 Python 基本表示形式耳奕,然后再使用 Pydantic 對(duì)其進(jìn)行解析绑青。這樣做的好處是你知道以后要處理的內(nèi)容。不再只是將 Dict[str, Any]
用作 type annotation,不再用沒用的的編輯器自動(dòng)完成屋群,不再檢查屬性是否在整個(gè)代碼中都存在闸婴。
要引入除默認(rèn) json
以外的其他 json 包,我建議使用此模式
對(duì)于 Flask芍躏,你可以使用其他 編碼器/解碼器邪乍,如下所示:
今天的內(nèi)容就到這里啦,希望這篇文章對(duì)你有所幫助对竣,喜歡不要忘記收藏庇楞、轉(zhuǎn)發(fā)、評(píng)論否纬,點(diǎn)點(diǎn)關(guān)注哦吕晌!