分享自己写的一个 Python 的 JSON 转 Model 库

datamodel

如果觉得好用,请在 此项目的 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 协议》,转载必须注明作者和本文链接
讨论数量: 1
Jason990420

我写了一个, 没有作的很深层, 仅供参考.

import json

class Data_Model():

    def __init__(self):
        pass

    def asdict(self):
        return self.__dict__

    def decoder(self, data):
        if isinstance(data, str):
            data = json.loads(data)
        return self._decoder(data)

    def _decoder(self, data):
        if isinstance(data, (tuple, list)):
            return [Person(**item) for item in data]
        elif isinstance(data, dict):
            return Person(**data)
        return None

    def __repr__(self):
        return f'{self.__class__.__name__}(' + ', '.join([
            f'{item}:{self.__getattribute__(item)}'
                for item in self.__dict__]) + ')'

class Person(Data_Model):

    def __init__(self, name:str='', age:int=0, height:int=0):
        super().__init__()
        self.name = name
        self.age = age
        self.height = height

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

data = """[{"name": "HjzCy", "age": "18", "height": "170"},
           {"name": "YDMS", "age": "15", "height": "176"}]"""
p_list = Person().decoder(data)
print(p_list)
6天前 评论
一代咩神 (楼主) 5天前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!