分享自己寫的一個 Python 的 JSON 轉 Model 庫

一代咩神發表於2020-05-19

如果覺得好用,請在 此專案的 github 地址 上給個 start 支援一下!

datamodel 是一個可以從 JSON 對映到 Python 類的模組。

支援:

  • 字典轉物件 ( dictobject );
  • 列表轉物件陣列 ( listList[object] );
  • 物件轉字典 ( objectdict );
  • 對多層級巢狀的資料結構支援友好。

目前網上並沒有一個比較好的 JSON to Model 庫,就算有,其寫法也大多繁瑣。由於做專案需要經常把從伺服器上請求到的 JSON 轉換到對應類的例項,於是決定自己寫一個。

安裝

pip install datamodel

使用

JSON 轉類物件

"""
包括需要繼承的 Datamodel 類,dataclasses 模組中的 dataclass 裝飾器;
以及 typing 模組中常用的 List 和 Dict 型別。
"""
from datamodel import *

@dataclass
class Person(Datamodel):
    name: str = ''
    age: int = 0
    height: int = 0

p = Person.decoder({"name": "HjzCy",
                    "age": 18,
                    "height": 170
                    })

# Person(name='HjzCy', age=18, height=170)
print(p)

類物件轉 JSON

# {'name': 'HjzCy', 'age': 18, 'height': 170}
print(p.asdict())

JSON 轉型別例項列表

data = """[{
    "name": "HjzCy",
    "age": "18",
    "height": "170"
},
{
    "name": "YDMS",
    "age": "15",
    "height": "176"
}]"""

p_list = Person.decoder(data)
# [Person(name='HjzCy', age=18, height=170), Person(name='YDMS', age=15, height=176)]
print(p_list)

Api

  • decoder(cls, data: object)

    接收一個 dictliststr 型別的值作為引數,返回對應型別的例項對應型別的例項列表。並且支援自動型別轉換。例如:

    @dataclass
    class Ip(Datamodel):
        ip: str = ""
        port: int = 0
    
    # 注意: 被解析的 port 欄位值是 str 型
    # Ip(ip='192.136.1.95', port=8080)
    print(Ip.decoder({"ip": "192.136.1.95", "port": "8080"}))

    注意:如果某些值不能自動轉換到對應的型別,則保留預設值。例如:

    # Ip(ip='192.136.1.95', port=0)
    print(Ip.decoder({"ip": "192.136.1.95", "port": "a1234"}))
  • asdict()

    將類例項物件轉換為對應欄位的字典。

使用說明

  1. 類必須經過 @dataclass 修飾

    python 3.7 的新特性,為簡單起見,約束所有型別必須使用。參閱 理解 Python 的 Dataclasses

  2. 必須為所有屬性提供預設值 ( 可為 None )

    暫時強制遵守。原因我要在 decoder 方法中例項化傳進來的類,如果該類中包含只是定義而不初始化的欄位時,就會報錯。例如:

     @dataclass
     class Person:
         name: str
         age: int

    Person 傳到 decoder 方法中會報錯!

  3. 不會檢測 __init__ 中定義的屬性

    如果你已經使用了 @dataclass 修飾類,也許就沒必要在定義一個 __init__ 方法了。如果需要,請在 __post_init_ 方法中執行初始化後要執行的額外操作。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章