JSON
JSON作為目前最流行的傳輸格式,在Python中也有相應(yīng)的實(shí)現(xiàn)方式。由于JSON格式的文本可以跨平臺并且簡單易用,因此被廣泛傳播。因此,我們今天的主要討論內(nèi)容是如何熟練地應(yīng)用Python的JSON庫來處理將JSON映射到文本,以及如何從文本映射到對象中?,F(xiàn)在,讓我們開始探討這個(gè)話題。
官方j(luò)son庫
在Python中,官方提供了多個(gè)JSON庫,包括標(biāo)準(zhǔn)庫中的json、marshal和pickle。其中,我個(gè)人比較喜歡使用json庫,因?yàn)閜ickle存在一些反序列化漏洞,并且它處理的是二進(jìn)制類型的數(shù)據(jù)。相比之下,json更類似于我們在Java中使用的fastjson,但它們之間仍然存在一些明顯的差異。接下來,我們繼續(xù)深入了解一下。
簡單用法
import json
json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
# '["foo", {"bar": ["baz", null, 1.0, 2]}]'
print(json.dumps("\"foo\bar"))
# "\"foo\bar"
print(json.dumps('\u1234'))
# "\u1234"
print(json.dumps('\\'))
# "\\"
print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
# {"a": 0, "b": 0, "c": 0}
from io import StringIO
io = StringIO()
json.dump(['streaming API'], io)
io.getvalue()
# '["streaming API"]'
上面提到的是官方提供的一些JSON庫的示例,我們不再深入討論。現(xiàn)在,讓我們來講解一下在工作中如何使用JSON進(jìn)行對象的序列化和反序列化。
進(jìn)階用法
當(dāng)前端返回給后端一串JSON文本時(shí),我們可以使用json.loads()方法將其正確映射到Python對象中。這個(gè)過程稱為反序列化。使用對象來處理數(shù)據(jù)會更規(guī)范一些,盡管對于一些快速開發(fā)來說,直接使用字典可能更方便。不過,我可以給你演示一下如何使用對象進(jìn)行反序列化。
首先,我們可以定義一個(gè)類來表示我們要映射的對象,然后利用json.loads()方法將JSON文本轉(zhuǎn)換為字典。接著,我們可以使用字典的鍵值對來為對象的屬性賦值。這樣,我們就成功地將JSON文本映射到了對象中。讓我來給你演示一下:
{"status":1,"info":"成功","data":{"id":"52","age":"70"}}
上面是我們接收的參數(shù),我們需要對其進(jìn)行處理,將其映射到相應(yīng)的對象中。
import json
class Response_data:
def __init__(self, id, feed_id):
super().__init__()
self.id = id
self.feed_id = feed_id
class Response:
def __init__(self, status=None, info=None, data=None) -> None:
super().__init__()
self.status = status
self.info = info
self.data = data
def to_json(self):
return {
"status": self.status,
"info": self.info,
"data": self.data.__dict__ if self.data else None
}
@staticmethod
def object_hook(d):
if "status" in d :
return Response(d['status'], d['info'], d['data'])
else:
return Response_data(d['id'],d['feed_id'])
body = '{"status":1,"info":"發(fā)布成功","data":{"id":"52","feed_id":"70"}}'
resp = json.loads(body, object_hook=Response.object_hook)
print(json.dumps(resp.to_json(),ensure_ascii=False))
在上述代碼中,我們使用了object_hook參數(shù)。object_hook參數(shù)的主要作用是用來自定義解碼函數(shù)。它的入?yún)⑹菢?biāo)準(zhǔn)反序列化后的字典,我們可以根據(jù)自己的規(guī)則將其轉(zhuǎn)換為所需的格式。
為什么我需要在object_hook中編寫if判斷呢?這是因?yàn)閛bject_hook參數(shù)在反序列化時(shí)是遞歸的。由于我的JSON文本是嵌套的結(jié)構(gòu),所以每一層嵌套都會遞歸一次。因此,我需要先封裝好Response_data,然后才能繼續(xù)封裝Response。這與Java中的JSON序列化有很大的不同。在Java中,我們不需要關(guān)注這么多細(xì)節(jié)。但是在Python中,我們不僅需要指定參數(shù)名稱,還需要處理好嵌套結(jié)構(gòu)。
如果你在解析中文時(shí)遇到問題,很可能是由于默認(rèn)的編碼格式不支持中文字符。為了解決這個(gè)問題,你可以嘗試使用ensure_ascii=False參數(shù)。通過設(shè)置這個(gè)參數(shù),可以禁用ASCII編碼,從而保留中文字符的原始形式。
多說一句
json庫是在Python2.6版中引入的,因此如果您使用的是更早版本的Python,您可以通過PyPI獲取simplejson庫來實(shí)現(xiàn)相同的功能。
json 類型轉(zhuǎn)換到 python 的類型對照表:
JSON | Python |
---|---|
object | dict |
array | list |
string | unicode |
number (int) | int, long |
number (real) | float |
true | True |
false | False |
null | None |
三方j(luò)son庫
demjson
Demjson是一個(gè)Python的第三方模塊庫,它提供了編碼和解碼JSON數(shù)據(jù)的功能,并且還包含了JSONLint的格式化和校驗(yàn)功能。此外,Demjson還支持hook,可以通過decode函數(shù)配置和set_hook函數(shù)配置兩種方式進(jìn)行配置。
你可以在以下網(wǎng)址找到Demjson的Github地址:https://github.com/dmeranda/demjson。同時(shí),你也可以在官方地址http://deron.meranda.us/python/demjson/上了解更多關(guān)于Demjson的信息。
decode函數(shù)是Demjson提供的一個(gè)功能強(qiáng)大的函數(shù),它可以接受多個(gè)參數(shù),其中包括hook函數(shù)。通過鍵值對的方式指定hook函數(shù),鍵是hook函數(shù)的名稱,而值是hook函數(shù)本身。
如果你在安裝Demjson時(shí)遇到了報(bào)錯(cuò),可能是因?yàn)樾枰档蛃etuptools的版本到57.5.0。不過我就不進(jìn)行實(shí)驗(yàn)和驗(yàn)證了。
orjson
在日常的開發(fā)工作中,我們經(jīng)常需要將一些數(shù)據(jù)存儲為JSON格式。而最常用的方法是使用Python原生的JSON庫。然而,我們發(fā)現(xiàn)該庫的速度較慢,特別是當(dāng)數(shù)據(jù)量過大時(shí),使用起來非常不便。幸運(yùn)的是,我們發(fā)現(xiàn)了orjson這個(gè)強(qiáng)大的工具,它不僅支持多種類型的數(shù)據(jù)序列化,還可以根據(jù)開發(fā)者的需求進(jìn)行定制化輸出。與其他第三方JSON庫相比,orjson具有更高的效率,因此在處理大量數(shù)據(jù)時(shí),它是一個(gè)更好的選擇。
我們來看一下它是如何運(yùn)作的。下面是一個(gè)使用dataclasses模塊的示例代碼:
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
# 假設(shè)您有一個(gè)包含 JSON 數(shù)據(jù)的字符串
json_data = '{"name": "xiaoyu", "age": 18}'
# 使用 orjson 反序列化 JSON 數(shù)據(jù)
import orjson
data_dict = orjson.loads(json_data)
# 將字典轉(zhuǎn)換為 Person 對象
person = Person(**data_dict)
# 現(xiàn)在,您可以像訪問對象屬性一樣訪問 person 對象的屬性
print(person.name) # 輸出 "xiaoyu"
print(person.age) # 輸出 18
經(jīng)過仔細(xì)觀察,我發(fā)現(xiàn)這兩種方式看起來確實(shí)非常相似,官方的JSON模塊也能實(shí)現(xiàn)相同的功能。但是當(dāng)我們嘗試將person對象轉(zhuǎn)換成字符串時(shí),官方的JSON模塊無法完成這個(gè)任務(wù),而orjson則可以輕松勝任。
orjson.dumps(person)
option參數(shù)
orjson還支持使用option參數(shù)來定制序列化的結(jié)果。當(dāng)然,還有很多其他的選項(xiàng)可以使用,但是由于太多了,我就不一一列舉了。不過,我可以簡單舉一個(gè)日期格式的例子,因?yàn)樵谖覀兊墓ぷ髦?,通常需要對日期格式進(jìn)行處理。
option=orjson.OPT_OMIT_MICROSECONDS: 序列化的日期時(shí)間對象將以字符串形式呈現(xiàn),而不是默認(rèn)的 ISO 8601 格式。這個(gè)選項(xiàng)在某些情況下可能更加便利,尤其是在與其他系統(tǒng)進(jìn)行數(shù)據(jù)交換時(shí)。通過使用該選項(xiàng),您可以確保日期時(shí)間對象的格式與其他系統(tǒng)的要求相匹配,從而簡化數(shù)據(jù)交換的過程。
import orjson
from datetime import datetime
data = {"name": "xiaoyu", "dob": datetime(2020, 5, 1)}
json_data = orjson.dumps(data, option=orjson.OPT_OMIT_MICROSECONDS)
print(json_data.decode())
為什么需要進(jìn)行解碼呢?原因主要在于orjson返回的是二進(jìn)制數(shù)據(jù),而我們需要將其轉(zhuǎn)換為字符串類型,因此需要進(jìn)行解碼操作。
總結(jié)
JSON是一種流行的數(shù)據(jù)傳輸格式,Python中有多種處理JSON的方式。官方的json庫是最常用的,它提供了簡單的用法來序列化和反序列化JSON文本。此外,它還支持自定義解碼函數(shù),可以將JSON映射到對象中。
在使用官方j(luò)son庫時(shí),可以使用dumps函數(shù)將Python對象轉(zhuǎn)換為JSON文本,也可以使用loads函數(shù)將JSON文本轉(zhuǎn)換為Python對象。如果需要自定義解碼函數(shù),可以使用object_hook參數(shù)來實(shí)現(xiàn)。
除了官方的json庫,還有一些第三方的庫可供選擇。例如,demjson庫提供了JSON數(shù)據(jù)的編碼和解碼功能,并支持hook函數(shù)。另外,orjson庫是一個(gè)高效的JSON庫,支持多種數(shù)據(jù)類型的序列化,并提供了定制化輸出的選項(xiàng)。文章來源:http://www.zghlxwxcb.cn/news/detail-817685.html
總之,掌握Python的JSON處理庫對于處理JSON數(shù)據(jù)非常重要,可以幫助我們在項(xiàng)目開發(fā)中更加高效地處理JSON數(shù)據(jù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-817685.html
到了這里,關(guān)于Java開發(fā)者的Python進(jìn)修指南:JSON利器之官方j(luò)son庫、demjson和orjson的實(shí)用指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!