欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python如何把不同類型數(shù)據(jù)的json序列化

 更新時間:2021年04月30日 11:52:35   作者:大江狗  
這篇文章主要介紹了Python如何把不同類型數(shù)據(jù)的json序列化,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下

現(xiàn)代網(wǎng)絡(luò)應(yīng)用Web APP或大型網(wǎng)站的后臺一般只有一個,然后客戶端卻是各種各樣的(iOS, android, 瀏覽器), 而且客戶端的開發(fā)語言很可能與后臺的開發(fā)語言不一樣。這時我們需要后臺能夠提供可以跨平臺跨語言的一種標(biāo)準(zhǔn)的數(shù)據(jù)交換格式供前后端溝通(這就是Web API的作用)。如今大家最常用的跨平臺跨語言數(shù)據(jù)交換格式就是JSON(JavaScript Object Notation)了。JSON是一種文本序列化格式(它輸出的是unicode文件,大多數(shù)時候會被編碼為utf-8),人們很容易進(jìn)行閱讀和編寫。python自帶的dumps方法很有用,能很容易將字典dict類型數(shù)據(jù)轉(zhuǎn)化為json格式,然后還有很多類型的數(shù)據(jù)(如日期,集合, 自定義的類和Django的QuerySet類型),我們需要自定義序列化方法才能將它們轉(zhuǎn)化為json格式。今天小編我就來對python的json模塊做下總結(jié),并詳細(xì)介紹如何把不同類型的數(shù)據(jù)json序列化。

何謂序列化(serialization)

每種編程語言都有各自的數(shù)據(jù)類型, 將屬于自己語言的數(shù)據(jù)類型或?qū)ο筠D(zhuǎn)換為可通過網(wǎng)絡(luò)傳輸或可以存儲到本地磁盤的數(shù)據(jù)格式(如:XML、JSON或特定格式的字節(jié)串)的過程稱為序列化(seralization);反之則稱為反序列化。

Python的JSON模塊

python自帶的json庫(無需額外安裝), 主要包含了dumps, loads, dump和load四種方法其作用分別如下所示。

  • json.loads() - 將json字符串轉(zhuǎn)換為python數(shù)據(jù)類型
  • json.dumps() - 將python數(shù)據(jù)類型轉(zhuǎn)化為json字符串
  • json.dump() - 將python輸入轉(zhuǎn)化為json格式存入磁盤文件
  • json.load() - 將磁盤文件中json格式數(shù)據(jù)轉(zhuǎn)換為python數(shù)據(jù)類型

python數(shù)據(jù)格式與json數(shù)據(jù)格式對應(yīng)轉(zhuǎn)換關(guān)系如下:

Python JSON
dict Object
list, tuple array
str string
int, float,  numbers
True true
False false
None null

你注意到了嗎? 還有很多python數(shù)據(jù)類型(set, datetime)不在上表中哦。

json的模塊dumps方法介紹 - python數(shù)據(jù)的序列化

json模塊的dumps方法可以將python常用數(shù)據(jù)格式轉(zhuǎn)化為json格式。該方法還提供了很多可選參數(shù)如ident, separators, ensure_ascii, sort_keys和default參數(shù)。這些參數(shù)都非常有用,我們會稍后逐一介紹。

dumps(obj, skipkeys=False, ensure_ascii=True, 
      check_circular=True, allow_nan=True, 
      cls=None, indent=None, separators=None,
      default=None, sort_keys=False, **kw)

我們先來看看一個最簡單的例子。你注意到了嗎? 生成的json格式數(shù)據(jù)外面都加了單引號,這說明dict類型數(shù)據(jù)已經(jīng)轉(zhuǎn)化成了json字符串。

>>> import json
>>> json.dumps({"name":"John", "score": 112})
'{"name": "John", "score": 112}'

如果一個dict很長,生成的json字符串會非常長,這時我們可以設(shè)置indent參數(shù)使生成的json格式數(shù)據(jù)更優(yōu)美,更容易人們閱讀。代碼如下所示:

>>> import json
>>> json.dumps({"name":"John", "score": 112}, indent=4)
'{\n    "name": "John",\n    "score": 112\n}'
>>> print(json.dumps({"name":"John", "score": 112}, indent=4))
{
    "name": "John",
    "score": 112
}

然而使用indent參數(shù)的代價是json字符串里增加了額外的空白,機(jī)器閱讀根本不需要它們,

即使不用indent參數(shù),你會發(fā)現(xiàn)dumps生成的json字符串中的','號和':'號分隔符后都會附加一個默認(rèn)空白字符,我們可以通過separators參數(shù)重新指定分隔符,從而去除無用的空白字符,如下所示。這樣可以減少無用數(shù)據(jù)的的傳輸,節(jié)省帶寬增加數(shù)據(jù)傳輸速度。

>>> import json
>>> json.dumps({"name":"John", "score": 112})
'{"name": "John", "score": 112}'

# 使用separators選項(xiàng)
>>> json.dumps({"name":"John", "score": 112}, separators=(',',':'))
'{"name":"John","score":112}'

如果字符串有非ASCII字符(比如中文),它們在json序列化時都會被轉(zhuǎn)義成'\uXXXX'組成的ascii字符串。如果想得到更加易讀的字符串,可以設(shè)置ensure_ascii=False。

>>> import json
>>> json.dumps({"Name":"小明", "Age": 16})
'{"Name": "\\u5c0f\\u660e", "Age": 16}'

# 設(shè)置ensure_ascii=False
>>> json.dumps({"Name":"小明", "Age": 16}, ensure_ascii=False)
'{"Name": "小明", "Age": 16}'

一般的dict默認(rèn)是無序的,你還可以設(shè)置sort_keys = True對生成的json格式數(shù)據(jù)進(jìn)行排序,這里就不演示了。default參數(shù)我們后面會重點(diǎn)介紹。

json模塊的dump,loads和load方法介紹

與dumps方法不同,json模塊的dump方法用于將生成的json數(shù)據(jù)寫入磁盤文件。其用法和dumps類似,唯一不同的是需要指定需要寫入的文件,具體用法如下所示:

import json
with open("json.txt", 'w') as f:
   json.dump({"Name":"小明", "Age": 16}, f, ensure_ascii=True)

json的loads方法用于將json格式數(shù)據(jù)轉(zhuǎn)化為python格式,實(shí)現(xiàn)數(shù)據(jù)的反序列化,如下所示。千萬別忘了在json符串外的單引號哦。

>>> import json
>>> json.loads('{"Name": "小明", "Age": 16}')
{'Name': '小明', 'Age': 16}

json的load方法與loads用法相似,不過它需要指定存有json數(shù)據(jù)的文件。

>>> import json
>>> with open("json.txt", 'r') as f:
    json.load(f)

很多python格式數(shù)據(jù)不能直接被dumps方法序列化

很多python數(shù)據(jù)類型(比如日期,集合和自定義的類)并不能直接被dumps方法序列化,這時會出現(xiàn) xxx is not JSON serializable的錯誤,如下面代碼所示。當(dāng)出現(xiàn)類似錯誤時,我們有兩種解決方案。

  • 通過數(shù)據(jù)類型轉(zhuǎn)換函數(shù)實(shí)現(xiàn)
  • 通過繼承JSONEncoder和JSONDecoder類實(shí)現(xiàn)
>>> import json
>>> from datetime import datetime

# DateTime類型
>>> json.dumps({"date":datetime.now()})
Traceback (most recent call last):
TypeError: Object of type 'datetime' is not JSON serializable

# 自定義的User類
>>> class User(object):
        def __init__(self, name):
            self.name = name

>>> json.dumps(User("John"))

Traceback (most recent call last):
TypeError: Object of type 'User' is not JSON serializable

解決方案一: 編寫數(shù)據(jù)類型轉(zhuǎn)換函數(shù)

該方法的工作原理是先編寫數(shù)據(jù)類型轉(zhuǎn)化函數(shù),通過設(shè)置dumps方法里的default參數(shù)調(diào)用格式轉(zhuǎn)化函數(shù),將dumps方法不支持的數(shù)類型先轉(zhuǎn)化為字符串格式,再實(shí)現(xiàn)json序列化。

# 將datetime格式數(shù)據(jù)json化
>> > import json
>> > from datetime import datetime
>> > def date_to_str(obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        return TypeError

>> > json.dumps({"date": datetime.now()}, default=date_to_str)
'{"date": "2018-09-22 21:25:42"}'

# 將set類型數(shù)據(jù)json化
>> > import json
>> > set_data = {'my_set': {1, 2, 3}}

>> > def set_to_list(obj):
        if isinstance(obj, set):
            return list(obj)
        raise TypeError

>> > result = json.dumps(set_data, default=set_to_list)

對于我們自定義的類, 使用dumps方法時我們一般要先編寫obj_to_dict方法,將object轉(zhuǎn)化為字典dict再JSON序列化。同理,使用loads方法對json數(shù)據(jù)反序列化時,我們還需要編寫dict_to_obj方法,通過default參數(shù)調(diào)用。下面這2段代碼是比較通用的對象(object)與字典(dict)互轉(zhuǎn)的經(jīng)典代碼,請用微信收藏后再看。

# 將自定義的類轉(zhuǎn)化為字典,dumps方法使用
def obj_to_dict(obj):
    d = {}
    d['__class__'] = obj.__class__.__name__
    d['__module__'] = obj.__module__
    d.update(obj.__dict__)
    return d

# 將字典轉(zhuǎn)化為自定義的類,loads方法使用
def dict_to_obj(d):
    if '__class__' in d:
        class_name = d.pop('__class__')
        module_name = d.pop('__module__')
        module = __import__(module_name)
        class_ = getattr(module, class_name)
        args = dict((key.encode('ascii'), value) for key, value in d.items())
        instance = class_(**args)
    else:
        instance = d
    return instance

解決方案二: 繼承JSONEncoder類和JSONDecode類

另一個解決方案是繼承JSONEncoder類和JSONDecode類定義自己的編碼Encoder類,然后使用cls=MyEncoder,來調(diào)用編碼器。比如下例中我們定義了自己的DateTimeEncoder,將日期類型數(shù)據(jù)序列化。

from datetime import datetime, date
import json


class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        return json.JSONEncoder.default(self, obj)


json_data = {'num': 1, 'date': datetime.now()}
print(json.dumps(json_data, cls=DateTimeEncoder))

對于自定義的對象,我們也可以通過繼承JSONEncoder類實(shí)現(xiàn)它的序列化,如下所示:

import json
class User(object):
    def __init__(self, name):
        self.name = name

class MyJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        d = {}
        d['__class__'] = obj.__class__.__name__
        d['__module__'] = obj.__module__
        d.update(obj.__dict__)
        return d

user = User("John")
json.dumps(user, cls=MyJSONEncoder))

對于簡單的數(shù)據(jù)序列化,方案一更容易理解,代碼也更少。但當(dāng)需要傳輸?shù)臄?shù)據(jù)很大時,使用繼承JSONEncoder類來實(shí)現(xiàn)序列化時有個很大的好處,就是可以通過iterencode()方法把一個很大的數(shù)據(jù)對象分多次進(jìn)行序列化,這對于網(wǎng)絡(luò)持續(xù)傳輸或?qū)懭氪蟮奈募浅S杏谩H缦滤尽?/p>

>>> for chunk in MyJSONEncoder().iterencode(big_object):
...     print(chunk)

Django特有數(shù)據(jù)類型序列化

Django編程就是是python編程,以上所介紹的序列化方法對django也是適用的。不同的是Django還有自己專屬的數(shù)據(jù)類型比如QuerySet和ValueQuerySet類型數(shù)據(jù),還提供了更便捷的serializers類。使用serializers類可以輕易將QuerySet格式的數(shù)據(jù)轉(zhuǎn)化為json格式。

# Django Queryset數(shù)據(jù) to Json
from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all())
data1 = serializers.serialize("json", SomeModel.objects.all(), fields=('name','id'))
data2 = serializers.serialize("json", SomeModel.objects.filter(field = some_value))

有時候我們只需要查詢結(jié)果集的部分字段,可以使用values('字段名','字段名2')來要求返回的是哪些列的數(shù)據(jù).但是返回來的是ValuesQuerySet對象而不是QuerySet對象。ValuesQuerySet對象不能用 serializers.serialize() 方法序列化成json, 需要先轉(zhuǎn)換成list再用 json.dumps()方法序列化成json格式。示例代碼如下所示:

import json
from django.core.serializers.json import DjangoJSONEncoder

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
data4 = json.dumps(list(queryset), cls=DjangoJSONEncoder)

django-rest-framework

如果你要利用django開發(fā)restful的web API, 為不同客戶端提供序列化過的json格式數(shù)據(jù),django-rest-framework才是你真正需要的序列化工具。與django自帶的serializers類相比,rest framework支持用戶驗(yàn)證,查詢過濾和符合restful規(guī)范的url設(shè)計,我們后面會專門介紹。歡迎關(guān)注我的微信。

小結(jié)

我們介紹了何為JSON序列化以及python json模塊的dumps, loads, dump和load方法。我們還介紹了如何將dumps方法不支持的數(shù)據(jù)格式(如日期,集合, 自定義的類和Django的QuerySet類型)如何通過要自定義格式轉(zhuǎn)化函數(shù)和繼承JsonEncoder類將它們轉(zhuǎn)化為json格式。希望本文對你有所幫助。喜歡的給個贊吧!

以上就是Python如何把不同類型數(shù)據(jù)的json序列化的詳細(xì)內(nèi)容,更多關(guān)于python 數(shù)據(jù)json序列化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python量化交易詳細(xì)簡介

    Python量化交易詳細(xì)簡介

    這篇文章主要介紹了Python量化交易詳細(xì),??算法交易是使用自動化系統(tǒng)來執(zhí)行交易,這些交易是通過特定的算法以預(yù)測的方式執(zhí)行的沒有任何人為干預(yù)。依據(jù)數(shù)學(xué)模型對大數(shù)據(jù)進(jìn)行概率分析,使得長期收益期望最大化,下文詳細(xì)敘述,需要的朋友可以參考一下
    2022-03-03
  • python 如何把classification_report輸出到csv文件

    python 如何把classification_report輸出到csv文件

    這篇文章主要介紹了python 把classification_report輸出到csv文件的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • Jupyter notebook 遠(yuǎn)程配置及SSL加密教程

    Jupyter notebook 遠(yuǎn)程配置及SSL加密教程

    這篇文章主要介紹了Jupyter notebook 遠(yuǎn)程配置及SSL加密教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • python實(shí)現(xiàn)MySQL指定表增量同步數(shù)據(jù)到clickhouse的腳本

    python實(shí)現(xiàn)MySQL指定表增量同步數(shù)據(jù)到clickhouse的腳本

    這篇文章主要介紹了python實(shí)現(xiàn)MySQL指定表增量同步數(shù)據(jù)到clickhouse的腳本,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 使用python如何刪除同一文件夾下相似的圖片

    使用python如何刪除同一文件夾下相似的圖片

    這篇文章主要給大家介紹了關(guān)于利用python如何刪除同一文件夾下相似的圖片的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • python實(shí)現(xiàn)字符串連接的三種方法及其效率、適用場景詳解

    python實(shí)現(xiàn)字符串連接的三種方法及其效率、適用場景詳解

    本篇文章主要介紹了python實(shí)現(xiàn)字符串連接的三種方法及其效率、適用場景詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • Python英文文本分詞(無空格)模塊wordninja的使用實(shí)例

    Python英文文本分詞(無空格)模塊wordninja的使用實(shí)例

    今天小編就為大家分享一篇關(guān)于Python英文文本分詞(無空格)模塊wordninja的使用實(shí)例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Python基礎(chǔ)之元類詳解

    Python基礎(chǔ)之元類詳解

    這篇文章主要介紹了Python基礎(chǔ)之元類詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)python基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Python中pyautogui庫的使用方法匯總

    Python中pyautogui庫的使用方法匯總

    在使用Python做腳本的話,有兩個庫可以使用,一個為PyUserInput庫,另一個為pyautogui庫,本文給大家介紹下Python中pyautogui庫的使用方法匯總,感興趣的朋友跟隨小編一起看看吧
    2022-03-03
  • Python?hashlib模塊詳細(xì)講解使用方法

    Python?hashlib模塊詳細(xì)講解使用方法

    hashlib?是一個提供了一些流行的hash算法的?Python?標(biāo)準(zhǔn)庫.其中所包括的算法有?md5,?sha1,?sha224,?sha256,?sha384,?sha512.?另外,模塊中所定義的?new(name,?string=”)?方法可通過指定系統(tǒng)所支持的hash算法來構(gòu)造相應(yīng)的hash對象
    2022-11-11

最新評論