使数据类自动验证其类型

typed-json-dataclass的Python项目详细描述


键入的json数据类

Codacy BadgeActions StatuscodecovPyPI statusPyPI versionPyPI pyversionsPyPI - DownloadsMIT license

typed_json_dataclass是一个扩展python3.7的库。 dataclass功能一分为二 主要方式:

  1. 添加递归获取类字典定义的方法,从而使 数据类JSON可序列化
  2. 向数据类中添加少量类型验证,以便 验证给定的json是否与 期望。

通过将数据表示为数据类,并使传入的数据 在接收时验证,您可以轻松地在中实现Data Transfer Object (DTO)模式 你的python代码。

这个图书馆可以看作是 attrscattrs,和 marshamllow

开始

从pypi安装库:

pip install typed_json_dataclass

像平常一样使用dataclass decorator,但是添加TypedJsonMixinfrom 这个库,根据你的类定义。这将向所有数据类添加4个新方法:

  1. from_dict()
@classmethoddeffrom_dict(cls,raw_dict,*,mapping_mode=MappingMode.NoMap):"""Given a python dict, create an instance of the implementing class.    :raw_dict: A dictionary that represents the DTO to create    :mapping_mode: Format for properties    :returns: Returns an instance of the DTO, instantiated via the dict    """
  1. 来自_json()
@classmethoddeffrom_json(cls,raw_json,*,mapping_mode=MappingMode.NoMap):"""Given a raw json string, create an instance of the implementing class.    :raw_json: A json string that represents the DTO to create    :mapping_mode: Format for properties    :returns: Returns an instance of the DTO, instantiated via the json    """
  1. to_dict()
defto_dict(self,*,keep_none=False,mapping_mode=MappingMode.NoMap,warn_on_initvar=True):"""Express the DTO as a dictionary.    :keep_none: Filter keys that are None    :mapping_mode: Format for properties    :warn_on_initvar: Emit a warning if the instance contains non-default                      init-only variables.    :returns: Returns the instantiated DTO as a dictionary    """
  1. to_json()
defto_json(self,*,keep_none=False,mapping_mode=MappingMode.NoMap,warn_on_initvar=True):"""Express the DTO as a json string.    :keep_none: Filter keys that are None    :mapping_mode: Format for properties    :warn_on_initvar: Emit a warning if the instance contains non-default                      init-only variables.    :returns: Returns the instantiated DTO as a json string    """

示例

将数据类转换为json可序列化格式

fromtypingimportListfromdataclassesimportdataclassfromtyped_json_dataclassimportTypedJsonMixin@dataclassclassPerson(TypedJsonMixin):name:strage:int@dataclassclassFamily(TypedJsonMixin):people:List[Person]bob=Person(name='Bob',age=24)alice=Person(name='Alice',age=32)family=Family(people=[bob,alice])print(family.to_json())# => {"people": [{"name": "Bob", "age": 24}, {"name": "Alice", "age": 32}]}

如果您的数据与类型定义不匹配,将出现一个有用的错误:

fromdataclassesimportdataclassfromtyped_json_dataclassimportTypedJsonMixin@dataclassclassPerson(TypedJsonMixin):name:strage:intrequest_data='{"name":"Bob","age":"24"}'bob=Person.from_json(request_data)# => TypeError: Person.age is expected to be <class 'int'>, but value 24 with type <class 'str'> was found instead

您还可以解析来自pythondict的数据。只需使用.from_dict()函数即可:

fromdataclassesimportdataclassfromtyped_json_dataclassimportTypedJsonMixin@dataclassclassPerson(TypedJsonMixin):name:strage:intrequest_data_as_dict={'name':'Alice','age':'32'}alice=Person.from_dict(request_data_as_dict)# => TypeError: Person.age is expected to be <class 'int'>, but value 32 with type <class 'str'> was found instead

为自动映射设置映射模式

fromdataclassesimportdataclassfromtyped_json_dataclassimportTypedJsonMixin,MappingMode@dataclassclassPerson(TypedJsonMixin):person_name:strperson_age:intrequest_data_as_dict={'personName':'Alice','personAge':32}alice=Person.from_dict(request_data_as_dict,mapping_mode=MappingMode.SnakeCase)# => Person(person_name='Alice', person_age=32)

此映射模式对于在 camel case格式,但您希望您的对象是snake case并保持pep8 顺从。

限制和注意事项

只有init变量的数据类

支持具有init-only variables的数据类 是有限的。尽管to_dictto_json将转换数据类,但是 结果dict或json字符串将不包含init-only变量,因为 它们的值在初始化后不可用。这也意味着 以后不能从dict或json字符串实例化数据类,因为 只有init变量是数据类'__init__中的必需参数。 方法。TypedJsonMixin检测仅使用init的数据类的用法 变量,当它转换为dict或json字符串时发出警告,并且 拒绝用仅初始化变量实例化数据类。

第一个解决方法是仅向init提供默认值 变量:

@dataclassclassPerson(TypedJsonMixin):person_name:InitVar[str]=''person_first_name:str=''person_last_name:str=''def__post_init__(self,person_name):ifperson_name:# Instantiated directlyself.person_first_name,self.person_last_name=person_name.split()# Call TypedJsonMixin __post_init__ methodsuper().__post_init__()

note:没有参数的实例化,例如Person(),现在是 可能,尽管创建的实例随后将无效。

第二种解决方法是从数据类中删除init-only变量,然后 使用类方法执行__post_init__实例化:

@dataclassclassPerson(TypedJsonMixin):person_first_name:strperson_last_name:str@classmethoddefcreate(cls,person_name):first_name,last_name=person_name.split()cls(first_name,last_name)

最后,如果不打算从dict或 json字符串,并且只调用to_dictto_json方法,则 通过将warn_on_initvar=False作为关键字传递,可以抑制警告 方法调用中的参数。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
Android Java在活动之间传递值   java当实体中存在关系时,我可以只使用实体的id而不是从DB中获取实体吗?   bouncycastle Java运行SSHD服务器错误未找到类定义   java SWT/Swing>Threads n'Hell   java多线程数据库读取   java如何在Eclipse中轻松提交Git   java在哪里可以找到字符串相等比较的一组特定排序规则?   无连接表的java单向单域关系   java扩展三角文件   java spring。杰克逊。序列化。failonemptybeans   java无法加载请求的类:oracle。jdbc。驾驶员OracleDriver   java通过数组进行索引循环并打印出元素?   找不到eclipse错误类中的java提交Hadoop作业   Java:随机设定种子   java片段、异步任务和侦听器   java在分号后使用{}