pydantic导出模型

1.model.dict(...)

  • 将模型转换为字典的主要方法。子模型将递归转换为字典。
  • 参数如下:
    • include:要包含在返回的字典中的字段
    • exclude:要从返回的字典中排除的字段
    • by_alias:字段别名是否应用作返回字典中的键
    • exclude_unset:创建模型时未显式设置的字段是否应从返回的字典中排除;
    • exclude_defaults:是否应从返回的字典中排除等于其默认值(无论是否设置)的字段;
    • exclude_none:是否应从返回的字典中排除等于的字段;
from pydantic import BaseModel


class BarModel(BaseModel):
    whatever: int


class FooBarModel(BaseModel):
    banana: float
    foo: str
    bar: BarModel


m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})

# returns a dictionary:
print(m.dict())
"""
{
    'banana': 3.14,
    'foo': 'hello',
    'bar': {'whatever': 123},
}
"""
print(m.dict(include={'foo', 'bar'}))
# {'foo': 'hello', 'bar': {'whatever': 123}}
print(m.dict(exclude={'foo', 'bar'}))
# {'banana': 3.14}
  • 高级包含和排除
from pydantic import BaseModel, SecretStr


class User(BaseModel):
    id: int
    username: str
    password: SecretStr


class Transaction(BaseModel):
    id: str
    user: User
    value: int


t = Transaction(
    id='1234567890',
    user=User(
        id=42,
        username='JohnDoe',
        password='hashedpassword'
    ),
    value=9876543210,
)

# using a set:
print(t.dict(exclude={'user', 'value'}))  # {'id': '1234567890'}

# using a dict: 对深层嵌套对象进行处理
print(t.dict(exclude={'user': {'username', 'password'}, 'value': True}))  # {'id': '1234567890', 'user': {'id': 42}}

print(t.dict(include={'id': True, 'user': {'id'}}))  # {'id': '1234567890', 'user': {'id': 42}}
import datetime
from typing import List

from pydantic import BaseModel, SecretStr


class Country(BaseModel):
    name: str
    phone_code: int


class Address(BaseModel):
    post_code: int
    country: Country


class CardDetails(BaseModel):
    number: SecretStr
    expires: datetime.date


class Hobby(BaseModel):
    name: str
    info: str


class User(BaseModel):
    first_name: str
    second_name: str
    address: Address
    card_details: CardDetails
    hobbies: List[Hobby]


user = User(
    first_name='John',
    second_name='Doe',
    address=Address(
        post_code=123456,
        country=Country(
            name='USA',
            phone_code=1
        )
    ),
    card_details=CardDetails(
        number=4212934504460000,
        expires=datetime.date(2020, 5, 1)
    ),
    hobbies=[
        Hobby(name='Programming', info='Writing code and stuff'),
        Hobby(name='Gaming', info='Hell Yeah!!!'),
    ],
)

exclude_keys = {
    'second_name': True,
    'address': {'post_code': True, 'country': {'phone_code'}},
    'card_details': True,
    # You can exclude fields from specific members of a tuple/list by index:
    'hobbies': {-1: {'info'}},
}

include_keys = {
    'first_name': True,
    'address': {'country': {'name'}},
    'hobbies': {0: True, -1: {'name'}},
}

# would be the same as user.dict(exclude=exclude_keys) in this case:
print(user.dict(include=include_keys))
"""
{
    'first_name': 'John',
    'address': {'country': {'name': 'USA'}},
    'hobbies': [
        {
            'name': 'Programming',
            'info': 'Writing code and stuff',
        },
        {'name': 'Gaming'},
    ],
}
"""

# 从列表对象中排除所有子元素的info属性
print(user.dict(exclude={'hobbies': {'__all__': {'info'}}}))
"""
{
    'first_name': 'John',
    'second_name': 'Doe',
    'address': {
        'post_code': 123456,
        'country': {'name': 'USA', 'phone_code': 1},
    },
    'card_details': {
        'number': SecretStr('**********'),
        'expires': datetime.date(2020, 5, 1),
    },
    'hobbies': [{'name': 'Programming'}, {'name': 'Gaming'}],
}
"""

2.model.json(...)

  • 法会将模型序列化为 JSON

  • encoder:支持使用自定义的编码器函数

  • json_encoders的使用(模型继承期间,它们也会合并,子编码器优先于父编码器)

from datetime import datetime, timedelta
from pydantic import BaseModel
from pydantic.json import timedelta_isoformat


class WithCustomEncoders(BaseModel):
    dt: datetime
    diff: timedelta

    class Config:
        json_encoders = {
            # 参数类型:处理方法
            datetime: lambda v: v.timestamp(),
            timedelta: timedelta_isoformat,
        }


m = WithCustomEncoders(dt=datetime(2032, 6, 1), diff=timedelta(hours=100))
print(m.json())
# {"dt": 1969660800.0, "diff": "P4DT4H0M0.000000S"}
  • models_as_dict=False:模型作为字典序列化对象,是否进行序列化
from typing import List, Optional

from pydantic import BaseModel


class Address(BaseModel):
    city: str
    country: str


class User(BaseModel):
    name: str
    address: Address
    friends: Optional[List['User']] = None

    class Config:
        json_encoders = {
            # 将Address和User作为序列化对象
            Address: lambda a: f'{a.city} ({a.country})',
            'User': lambda u: f'{u.name} in {u.address.city} '
                              f'({u.address.country[:2].upper()})',
            # "address": lambda a: f'{a.city} ({a.country})',
            # 'friends': lambda u: f'{u.name} in {u.address.city} '
            #                   f'({u.address.country[:2].upper()})',
        }


wolfgang = User(
    name='Wolfgang',
    address=Address(city='Berlin', country='Deutschland'),
    friends=[
        User(name='Pierre', address=Address(city='Paris', country='France')),
        User(name='John', address=Address(city='London', country='UK')),
    ],
)

# 对其进行序列化
print(wolfgang.json(models_as_dict=False))
"""
{"name": "Wolfgang", "address": "Berlin (Deutschland)", "friends": ["Pierre in Paris (FR)", "John in London (UK)"]}
"""

# 不对其进行序列化
print(wolfgang.json())
"""
{"name": "Wolfgang", "address": {"city": "Berlin", "country": "Deutschland"}, "friends": [{"name": "Pierre", "address": {"city": "Paris", "country": "France"}, "friends": null}, {"name": "John", "address": {"city": "London", "country": "UK"}, "friends": null}]}
"""
posted @ 2022-06-16 19:17  fatpuffer  阅读(372)  评论(0编辑  收藏  举报