跳转到主要内容

将数据类转换为marshmallow模式的Python库。

项目描述

marshmallow-dataclass

Test Workflow Status (master branch) PyPI version marshmallow 3 compatible download stats

从数据类自动生成marshmallow模式。

from dataclasses import dataclass, field
from typing import List, Optional

import marshmallow_dataclass
import marshmallow.validate


@dataclass
class Building:
    # field metadata is used to instantiate the marshmallow field
    height: float = field(metadata={"validate": marshmallow.validate.Range(min=0)})
    name: str = field(default="anonymous")


@dataclass
class City:
    name: Optional[str]
    buildings: List[Building] = field(default_factory=list)


city_schema = marshmallow_dataclass.class_schema(City)()

city = city_schema.load(
    {"name": "Paris", "buildings": [{"name": "Eiffel Tower", "height": 324}]}
)
# => City(name='Paris', buildings=[Building(height=324.0, name='Eiffel Tower')])

city_dict = city_schema.dump(city)
# => {'name': 'Paris', 'buildings': [{'name': 'Eiffel Tower', 'height': 324.0}]}

为什么

在Python中使用模式通常意味着既有表示数据的类,又有表示其模式的类,这会导致重复的代码可能不一致。自Python 3.6起,可以为类成员定义类型,这允许库自动生成模式。

因此,您可以以允许您静态检查代码是否与文档匹配的方式记录API。

安装

此软件包托管在PyPI上

pip3 install marshmallow-dataclass
pip3 install "marshmallow-dataclass"

marshmallow 2支持

marshmallow-dataclass不再支持marshmallow 2。如果您需要marshmallow 2兼容性,请安装marshmallow_dataclass<6.0

使用

使用class_schema函数从dataclass生成一个marshmallow Schema类。

from dataclasses import dataclass
from datetime import date

import marshmallow_dataclass


@dataclass
class Person:
    name: str
    birth: date


PersonSchema = marshmallow_dataclass.class_schema(Person)

您的字段类型必须是 marshmallow 支持的基本类型之一(例如 floatstrbytesdatetime 等),Union 或其他数据类。

Union(反)序列化强制转换

通常是指 Union 类型;Union[X, Y] 从集合论的角度来看意味着 XY,即一个无序集,然而子类型的顺序定义了在尝试反序列化或序列化值时的优先级,具体请参见此处

例如,

from typing import Union

from dataclasses import dataclass


@dataclass
class Person:
    name: str
    age: Union[int, float]


PersonSchema = marshmallow_dataclass.class_schema(Person)
PersonSchema().load({"name": "jane", "age": 50.0})
# => Person(name="jane", age=50)

会首先尝试将 50.0 强制转换为 int。如果不想进行强制转换,可以使用 Any 类型,但要注意,如果没有额外的验证,则不会进行类型检查。

自定义生成的字段

要向生成的 marshmallow 字段传递参数(例如,validateload_onlydump_only 等),请将它们传递给 field 函数的 metadata 参数。

注意,从版本 4 开始,marshmallow 将禁止传递任意参数,因此任何附加的元数据都应该放在它自己的 metadata 字典中。

from dataclasses import dataclass, field
import marshmallow_dataclass
import marshmallow.validate


@dataclass
class Person:
    name: str = field(
        metadata=dict(
            load_only=True, metadata=dict(description="The person's first name")
        )
    )
    height: float = field(metadata=dict(validate=marshmallow.validate.Range(min=0)))


PersonSchema = marshmallow_dataclass.class_schema(Person)

@dataclass 快捷方式

marshmallow_dataclass 提供了一个与标准库中的 @dataclasses.dataclass 相似行为的 @dataclass 装饰器,并添加了一个带有生成的 marshmallow Schema 属性。

# Use marshmallow_dataclass's @dataclass shortcut
from marshmallow_dataclass import dataclass


@dataclass
class Point:
    x: float
    y: float


Point.Schema().dump(Point(4, 2))
# => {'x': 4, 'y': 2}

注意:由于 .Schema 属性是动态添加的,可能会混淆类型检查器。为了避免这种情况,可以将 Schema 声明为 ClassVar

from typing import ClassVar, Type

from marshmallow_dataclass import dataclass
from marshmallow import Schema


@dataclass
class Point:
    x: float
    y: float
    Schema: ClassVar[Type[Schema]] = Schema

自定义基础 Schema

您还可以从自己的基础 Schema 类派生所有 Schema(请参阅marshmallow 关于扩展 Schema 的文档)。这允许您实现自定义(反)序列化行为,例如指定类与 marshmallow 字段之间的自定义映射,或在序列化时重命名字段。

类与字段之间的自定义映射

class BaseSchema(marshmallow.Schema):
    TYPE_MAPPING = {CustomType: CustomField, List: CustomListField}


class Sample:
    my_custom: CustomType
    my_custom_list: List[int]


SampleSchema = marshmallow_dataclass.class_schema(Sample, base_schema=BaseSchema)
# SampleSchema now serializes my_custom using the CustomField marshmallow field
# and serializes my_custom_list using the CustomListField marshmallow field

在序列化时重命名字段

import marshmallow
import marshmallow_dataclass


class UppercaseSchema(marshmallow.Schema):
    """A Schema that marshals data with uppercased keys."""

    def on_bind_field(self, field_name, field_obj):
        field_obj.data_key = (field_obj.data_key or field_name).upper()


class Sample:
    my_text: str
    my_int: int


SampleSchema = marshmallow_dataclass.class_schema(Sample, base_schema=UppercaseSchema)

SampleSchema().dump(Sample(my_text="warm words", my_int=1))
# -> {"MY_TEXT": "warm words", "MY_INT": 1}

您还可以将 base_schema 传递给 marshmallow_dataclass.dataclass

@marshmallow_dataclass.dataclass(base_schema=UppercaseSchema)
class Sample:
    my_text: str
    my_int: int

请参阅 marshmallow 关于扩展 Schema 的文档

自定义类型别名

此库允许您使用 Python 的 Annotated 类型 PEP-593 来指定自定义 marshmallow 字段。

from typing import Annotated
import marshmallow.fields as mf
import marshmallow.validate as mv

IPv4 = Annotated[str, mf.String(validate=mv.Regexp(r"^([0-9]{1,3}\\.){3}[0-9]{1,3}$"))]

您还可以传递一个 marshmallow 字段类。

from typing import Annotated
import marshmallow
from marshmallow_dataclass import NewType

Email = Annotated[str, marshmallow.fields.Email]

为了方便起见,提供了一些自定义类型

from marshmallow_dataclass.typing import Email, Url

当使用 Python 3.8 时,必须从 typing_extensions 包导入 Annotated

# Version agnostic import code:
if sys.version_info >= (3, 9):
    from typing import Annotated
else:
    from typing_extensions import Annotated

自定义 NewType 声明 [已弃用]

NewType 已弃用,改用上面描述的类型别名。

此库导出 NewType 函数以创建生成 自定义 marshmallow 字段 的类型。

NewType 的关键字参数传递给 marshmallow 字段构造函数。

import marshmallow.validate
from marshmallow_dataclass import NewType

IPv4 = NewType(
    "IPv4", str, validate=marshmallow.validate.Regexp(r"^([0-9]{1,3}\\.){3}[0-9]{1,3}$")
)

您还可以将 marshmallow 字段传递给 NewType

import marshmallow
from marshmallow_dataclass import NewType

Email = NewType("Email", str, field=marshmallow.fields.Email)

注意:如果您使用 mypy,您会注意到如果使用 NewType 定义的变量在类型注解中使用,mypy 会抛出一个错误。为了解决这个问题,将 marshmallow_dataclass.mypy 插件添加到您的 mypy 配置中,例如。

[mypy]
plugins = marshmallow_dataclass.mypy
# ...

Meta 选项

Meta 选项 的设置方式与 marshmallow 的 Schema 相同。

from marshmallow_dataclass import dataclass


@dataclass
class Point:
    x: float
    y: float

    class Meta:
        ordered = True

文档

项目文档托管在GitHub Pages上:https://lovasoa.github.io/marshmallow_dataclass/

贡献

要安装此项目并在本地对其进行更改,请遵循CONTRIBUTING.md中的说明。

项目详情


发布历史 发布通知 | RSS订阅

下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

marshmallow_dataclass-8.7.1.tar.gz (32.1 kB 查看哈希值)

上传时间 源代码

构建分发

marshmallow_dataclass-8.7.1-py3-none-any.whl (19.1 kB 查看哈希值)

上传时间 Python 3

由以下支持