Serialisatie
Naast het rechtstreeks benaderen van modelattributen via hun veldnamen (bijvoorbeeld model.foobar
), kunnen modellen op een aantal manieren worden geconverteerd, gedumpt, geserialiseerd en geëxporteerd.
!!! tip "Serialiseren versus dumpen" Pydantic gebruikt de termen "serialiseren" en "dump" door elkaar. Beide verwijzen naar het proces van het converteren van een model naar een woordenboek of een JSON-gecodeerde tekenreeks.
Outside of Pydantic, the word "serialize" usually refers to converting in-memory data into a string or bytes.
However, in the context of Pydantic, there is a very close relationship between converting an object from a more
structured form — such as a Pydantic model, a dataclass, etc. — into a less structured form comprised of
Python built-ins such as dict.
While we could (and on occasion, do) distinguish between these scenarios by using the word "dump" when converting to
primitives and "serialize" when converting to string, for practical purposes, we frequently use the word "serialize"
to refer to both of these situations, even though it does not always imply conversion to a string or bytes.
model.model_dump(...)
¶
??? api "API-documentatie" pydantic.main.BaseModel.model_dump
Dit is de belangrijkste manier om een model naar een woordenboek te converteren. Submodellen zullen recursief worden omgezet in woordenboeken.
!!! opmerking De enige uitzondering op submodellen die naar woordenboeken worden geconverteerd, is dat bij RootModel
en zijn subklassen de root
rechtstreeks wordt gedumpt, zonder een omhullend woordenboek. Ook dit gebeurt recursief.
!!! note U kunt berekende velden gebruiken om property
en cached_property
gegevens op te nemen in de uitvoer model.model_dump(...)
.
Voorbeeld:
from typing import Any, List, Optional
from pydantic import BaseModel, Field, Json
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
banana: Optional[float] = 1.1
foo: str = Field(serialization_alias='foo_alias')
bar: BarModel
m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123})
# returns a dictionary:
print(m.model_dump())
#> {'banana': 3.14, 'foo': 'hello', 'bar': {'whatever': 123}}
print(m.model_dump(include={'foo', 'bar'}))
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(m.model_dump(exclude={'foo', 'bar'}))
#> {'banana': 3.14}
print(m.model_dump(by_alias=True))
#> {'banana': 3.14, 'foo_alias': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(foo='hello', bar={'whatever': 123}).model_dump(
exclude_unset=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(banana=1.1, foo='hello', bar={'whatever': 123}).model_dump(
exclude_defaults=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(foo='hello', bar={'whatever': 123}).model_dump(
exclude_defaults=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
print(
FooBarModel(banana=None, foo='hello', bar={'whatever': 123}).model_dump(
exclude_none=True
)
)
#> {'foo': 'hello', 'bar': {'whatever': 123}}
class Model(BaseModel):
x: List[Json[Any]]
print(Model(x=['{"a": 1}', '[1, 2]']).model_dump())
#> {'x': [{'a': 1}, [1, 2]]}
print(Model(x=['{"a": 1}', '[1, 2]']).model_dump(round_trip=True))
#> {'x': ['{"a":1}', '[1,2]']}
model.model_dump_json(...)
¶
??? api "API-documentatie" pydantic.main.BaseModel.model_dump_json
De methode .model_dump_json()
serialiseert een model rechtstreeks naar een JSON-gecodeerde tekenreeks die equivalent is aan het resultaat dat wordt geproduceerd door .model_dump()
.
Zie argumenten voor meer informatie.
!!! opmerking Pydantic kan veel veelgebruikte typen serialiseren naar JSON die anders incompatibel zouden zijn met een eenvoudige json.dumps(foobar)
(bijv. datetime
, date
of UUID
) .
from datetime import datetime
from pydantic import BaseModel
class BarModel(BaseModel):
whatever: int
class FooBarModel(BaseModel):
foo: datetime
bar: BarModel
m = FooBarModel(foo=datetime(2032, 6, 1, 12, 13, 14), bar={'whatever': 123})
print(m.model_dump_json())
#> {"foo":"2032-06-01T12:13:14","bar":{"whatever":123}}
print(m.model_dump_json(indent=2))
"""
{
"foo": "2032-06-01T12:13:14",
"bar": {
"whatever": 123
}
}
"""
dict(model)
en iteratie¶
Pydantic-modellen kunnen ook worden geconverteerd naar woordenboeken met behulp van dict(model)
, en u kunt ook de velden van een model doorlopen met behulp van for field_name, field_value in model:
. Met deze aanpak worden de onbewerkte veldwaarden geretourneerd, zodat submodellen niet naar woordenboeken worden geconverteerd.
Voorbeeld:
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})
print(dict(m))
#> {'banana': 3.14, 'foo': 'hello', 'bar': BarModel(whatever=123)}
for name, value in m:
print(f'{name}: {value}')
#> banana: 3.14
#> foo: hello
#> bar: whatever=123
Merk ook op dat RootModel
wordt geconverteerd naar een woordenboek met de sleutel 'root'
.
Aangepaste serialisatiesystemen¶
Pydantic biedt verschillende functionele serializers om aan te passen hoe een model wordt geserialiseerd naar een woordenboek of JSON.
Serialisatie kan op een veld worden aangepast met behulp van de decorateur @field_serializer
, en op een model met behulp van de decorateur @model_serializer
.
from datetime import datetime, timedelta, timezone
from typing import Any, Dict
from pydantic import BaseModel, ConfigDict, field_serializer, model_serializer
class WithCustomEncoders(BaseModel):
model_config = ConfigDict(ser_json_timedelta='iso8601')
dt: datetime
diff: timedelta
@field_serializer('dt')
def serialize_dt(self, dt: datetime, _info):
return dt.timestamp()
m = WithCustomEncoders(
dt=datetime(2032, 6, 1, tzinfo=timezone.utc), diff=timedelta(hours=100)
)
print(m.model_dump_json())
#> {"dt":1969660800.0,"diff":"P4DT4H"}
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> Dict[str, Any]:
return {'x': f'serialized {self.x}'}
print(Model(x='test value').model_dump_json())
#> {"x":"serialized test value"}
!!! note Er kan ook één serialisatiefunctie voor alle velden worden aangeroepen door de speciale waarde '*' door te geven aan de @field_serializer
decorateur.
Bovendien kunt u met PlainSerializer
en WrapSerializer
een functie gebruiken om de uitvoer van serialisatie te wijzigen.
Beide serializers accepteren optionele argumenten, waaronder:
return_type
specificeert het retourtype voor de functie. Indien dit wordt weggelaten, wordt dit afgeleid uit de typeannotatie.when_used
geeft aan wanneer deze serializer moet worden gebruikt. Accepteert een tekenreeks met de waarden 'always', 'unless-none', 'json' en 'json-unless-none'. Standaard ingesteld op 'altijd'.
PlainSerializer
gebruikt een eenvoudige functie om de uitvoer van serialisatie te wijzigen.
from typing_extensions import Annotated
from pydantic import BaseModel
from pydantic.functional_serializers import PlainSerializer
FancyInt = Annotated[
int, PlainSerializer(lambda x: f'{x:,}', return_type=str, when_used='json')
]
class MyModel(BaseModel):
x: FancyInt
print(MyModel(x=1234).model_dump())
#> {'x': 1234}
print(MyModel(x=1234).model_dump(mode='json'))
#> {'x': '1,234'}
WrapSerializer
ontvangt de onbewerkte invoer samen met een handlerfunctie die de standaard serialisatielogica toepast, en kan de resulterende waarde wijzigen voordat deze wordt geretourneerd als de uiteindelijke uitvoer van de serialisatie.
from typing import Any
from typing_extensions import Annotated
from pydantic import BaseModel, SerializerFunctionWrapHandler
from pydantic.functional_serializers import WrapSerializer
def ser_wrap(v: Any, nxt: SerializerFunctionWrapHandler) -> str:
return f'{nxt(v + 1):,}'
FancyInt = Annotated[int, WrapSerializer(ser_wrap, when_used='json')]
class MyModel(BaseModel):
x: FancyInt
print(MyModel(x=1234).model_dump())
#> {'x': 1234}
print(MyModel(x=1234).model_dump(mode='json'))
#> {'x': '1,235'}
Het retourtype overschrijven bij het dumpen van een model¶
Hoewel de retourwaarde van .model_dump()
gewoonlijk kan worden omschreven als dict[str, Any]
, kun je door het gebruik van @model_serializer
er feitelijk voor zorgen dat het een waarde retourneert die niet overeenkomt met deze handtekening:
from pydantic import BaseModel, model_serializer
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> str:
return self.x
print(Model(x='not a dict').model_dump())
#> not a dict
Als je dit wilt doen en toch de juiste typecontrole voor deze methode wilt krijgen, kun je .model_dump()
overschrijven in een if TYPE_CHECKING:
blok:
from typing import TYPE_CHECKING, Any
from typing_extensions import Literal
from pydantic import BaseModel, model_serializer
class Model(BaseModel):
x: str
@model_serializer
def ser_model(self) -> str:
return self.x
if TYPE_CHECKING:
# Ensure type checkers see the correct return type
def model_dump(
self,
*,
mode: Literal['json', 'python'] | str = 'python',
include: Any = None,
exclude: Any = None,
by_alias: bool = False,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
round_trip: bool = False,
warnings: bool = True,
) -> str: ...
Deze truc wordt in RootModel
precies voor dit doel gebruikt.
Serialiseren van subklassen¶
Subklassen van standaardtypen¶
Subklassen van standaardtypen worden automatisch gedumpt zoals hun superklassen:
from datetime import date, timedelta
from typing import Any, Type
from pydantic_core import core_schema
from pydantic import BaseModel, GetCoreSchemaHandler
class DayThisYear(date):
"""
Contrived example of a special type of date that
takes an int and interprets it as a day in the current year
"""
@classmethod
def __get_pydantic_core_schema__(
cls, source: Type[Any], handler: GetCoreSchemaHandler
) -> core_schema.CoreSchema:
return core_schema.no_info_after_validator_function(
cls.validate,
core_schema.int_schema(),
serialization=core_schema.format_ser_schema('%Y-%m-%d'),
)
@classmethod
def validate(cls, v: int):
return date(2023, 1, 1) + timedelta(days=v)
class FooModel(BaseModel):
date: DayThisYear
m = FooModel(date=300)
print(m.model_dump_json())
#> {"date":"2023-10-28"}
Subklasse-instanties voor velden van BaseModel
, dataclasses, TypedDict
¶
Wanneer velden worden gebruikt waarvan de annotaties zelf structuurachtige typen zijn (bijvoorbeeld BaseModel
subklassen, dataklassen, enz.), is het standaardgedrag het serialiseren van de attribuutwaarde alsof het een instantie van het geannoteerde type is, zelfs als het een subklasse is. Meer specifiek worden alleen de velden van het geannoteerde type opgenomen in het gedumpte object:
from pydantic import BaseModel
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user: User
user = UserLogin(name='pydantic', password='hunter2')
m = OuterModel(user=user)
print(m)
#> user=UserLogin(name='pydantic', password='hunter2')
print(m.model_dump()) # note: the password field is not included
#> {'user': {'name': 'pydantic'}}
!!! waarschuwing "Migratiewaarschuwing" Dit gedrag is anders dan hoe het werkte in Pydantic V1, waar we altijd alle velden (subklasse) zouden opnemen bij het recursief dumpen van modellen naar dicts. De motivatie achter deze gedragsverandering is dat het ervoor zorgt dat u precies weet welke velden kunnen worden opgenomen bij het serialiseren, zelfs als subklassen worden doorgegeven bij het instantiëren van het object. Dit kan met name verrassingen helpen voorkomen bij het toevoegen van gevoelige informatie zoals geheimen als velden van subklassen.
Serialiseren met duck-typering 🦆¶
Wat is serialisatie met duck-typering?
Duck-typing serialization is the behavior of serializing an object based on the fields present in the object itself, rather than the fields present in the schema of the object. This means that when an object is serialized, fields present in a subclass, but not in the original schema, will be included in the serialized output.
This behavior was the default in Pydantic V1, but was changed in V2 to help ensure that you know precisely which fields would be included when serializing, even if subclasses get passed when instantiating the object. This helps prevent security risks when serializing subclasses with sensitive information, for example.
Als u serialisatiegedrag bij duck-typing in v1-stijl wilt, kunt u een runtime-instelling gebruiken of afzonderlijke typen annoteren.
- Veld-/typeniveau: gebruik de annotatie
SerializeAsAny
- Runtimeniveau: gebruik de vlag
serialize_as_any
bij het aanroepen vanmodel_dump()
ofmodel_dump_json()
We bespreken deze opties hieronder in meer detail:
SerializeAsAny
-annotatie:¶
Als u serialisatiegedrag bij duck-typing wilt, kunt u dit doen met behulp van de annotatie SerializeAsAny
voor een type:
from pydantic import BaseModel, SerializeAsAny
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
as_any: SerializeAsAny[User]
as_user: User
user = UserLogin(name='pydantic', password='password')
print(OuterModel(as_any=user, as_user=user).model_dump())
"""
{
'as_any': {'name': 'pydantic', 'password': 'password'},
'as_user': {'name': 'pydantic'},
}
"""
Wanneer een veld is geannoteerd als SerializeAsAny[<SomeType>]
, zal het validatiegedrag hetzelfde zijn als wanneer het geannoteerd zou zijn als <SomeType>
, en type-checkers zoals mypy zullen het attribuut ook behandelen alsof het het juiste type heeft. Maar bij het serialiseren wordt het veld geserialiseerd alsof de typehint voor het veld Any
is, waar de naam vandaan komt.
serialize_as_any
runtime-instelling¶
De runtime-instelling serialize_as_any
kan worden gebruikt om modelgegevens te serialiseren met of zonder serialisatiegedrag van duck-type. serialize_as_any
kan als trefwoordargument worden doorgegeven aan de methoden model_dump()
en model_dump_json
van BaseModel
s en RootModel
s. Het kan ook als trefwoordargument worden doorgegeven aan de methoden dump_python()
en dump_json()
van TypeAdapter
s.
Als serialize_as_any
is ingesteld op True
, wordt het model geserialiseerd met behulp van duck-type serialisatiegedrag, wat betekent dat het model het schema negeert en in plaats daarvan aan het object zelf vraagt hoe het moet worden geserialiseerd. Dit betekent in het bijzonder dat wanneer modelsubklassen worden geserialiseerd, velden die aanwezig zijn in de subklasse, maar niet in het oorspronkelijke schema, worden opgenomen.
Als serialize_as_any
is ingesteld op False
(wat de standaardinstelling is), wordt het model geserialiseerd met behulp van het schema, wat betekent dat velden die aanwezig zijn in een subklasse, maar niet in het oorspronkelijke schema, worden genegeerd.
!!! vraag "Waarom is deze vlag nuttig?" Soms wilt u er zeker van zijn dat, ongeacht welke velden in subklassen zijn toegevoegd, het geserialiseerde object alleen de velden bevat die in de oorspronkelijke typedefinitie zijn vermeld. Dit kan handig zijn als u zoiets als een password: str
veld in een subklasse toevoegt dat u niet per ongeluk in de geserialiseerde uitvoer wilt opnemen.
Bijvoorbeeld:
from pydantic import BaseModel
class User(BaseModel):
name: str
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user1: User
user2: User
user = UserLogin(name='pydantic', password='password')
outer_model = OuterModel(user1=user, user2=user)
print(outer_model.model_dump(serialize_as_any=True)) # (1)!
"""
{
'user1': {'name': 'pydantic', 'password': 'password'},
'user2': {'name': 'pydantic', 'password': 'password'},
}
"""
print(outer_model.model_dump(serialize_as_any=False)) # (2)!
#> {'user1': {'name': 'pydantic'}, 'user2': {'name': 'pydantic'}}
- Als
serialize_as_any
is ingesteld opTrue
, komt het resultaat overeen met dat van V1. - Als
serialize_as_any
is ingesteld opFalse
(de standaardwaarde van V2), worden velden die aanwezig zijn in de subklasse, maar niet in de basisklasse, niet opgenomen in de serialisatie.
Deze instelling wordt zelfs van kracht bij geneste en recursieve patronen. Bijvoorbeeld:
from typing import List
from pydantic import BaseModel
class User(BaseModel):
name: str
friends: List['User']
class UserLogin(User):
password: str
class OuterModel(BaseModel):
user: User
user = UserLogin(
name='samuel',
password='pydantic-pw',
friends=[UserLogin(name='sebastian', password='fastapi-pw', friends=[])],
)
print(OuterModel(user=user).model_dump(serialize_as_any=True)) # (1)!
"""
{
'user': {
'name': 'samuel',
'friends': [
{'name': 'sebastian', 'friends': [], 'password': 'fastapi-pw'}
],
'password': 'pydantic-pw',
}
}
"""
print(OuterModel(user=user).model_dump(serialize_as_any=False)) # (2)!
"""
{'user': {'name': 'samuel', 'friends': [{'name': 'sebastian', 'friends': []}]}}
"""
- Zelfs geneste
User
worden gedumpt met velden die uniek zijn voorUser
. - Zelfs geneste
User
worden gedumpt zonder velden die uniek zijn voorUser
.
!!! note Het gedrag van de runtimevlag serialize_as_any
is vrijwel hetzelfde als het gedrag van de annotatie SerializeAsAny
. Er zijn een paar genuanceerde verschillen die we proberen op te lossen, maar voor het grootste deel kun je van beide hetzelfde gedrag verwachten. Zie meer over de verschillen in dit actieve nummer
De standaard serialize_as_any
overschrijven (False)¶
U kunt de standaardinstelling voor serialize_as_any
overschrijven door een subklasse van BaseModel
te configureren die de standaardinstelling voor het serialize_as_any
argument overschrijft naar model_dump()
en model_dump_json()
, en die vervolgens gebruiken als de basisklasse (in plaats van pydantic.BaseModel
) voor elk model dat u gebruikt wil dit standaardgedrag hebben.
U kunt bijvoorbeeld het volgende doen als u standaard serialisatie van duck-typing wilt gebruiken:
from typing import Any, Dict
from pydantic import BaseModel, SecretStr
class MyBaseModel(BaseModel):
def model_dump(self, **kwargs) -> Dict[str, Any]:
return super().model_dump(serialize_as_any=True, **kwargs)
def model_dump_json(self, **kwargs) -> str:
return super().model_dump_json(serialize_as_any=True, **kwargs)
class User(MyBaseModel):
name: str
class UserInfo(User):
password: SecretStr
class OuterModel(MyBaseModel):
user: User
u = OuterModel(user=UserInfo(name='John', password='secret_pw'))
print(u.model_dump_json()) # (1)!
#> {"user":{"name":"John","password":"**********"}}
model_dump_json
maakt standaard gebruik van duck-typing serialisatiegedrag, wat betekent dat hetpassword
wordt opgenomen in de uitvoer.
pickle.dumps(model)
¶
Pydantic-modellen ondersteunen efficiënt beitsen en ontbeitsen.
import pickle
from pydantic import BaseModel
class FooBarModel(BaseModel):
a: str
b: int
m = FooBarModel(a='hello', b=123)
print(m)
#> a='hello' b=123
data = pickle.dumps(m)
print(data[:20])
#> b'\x80\x04\x95\x95\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main_'
m2 = pickle.loads(data)
print(m2)
#> a='hello' b=123
Geavanceerd opnemen en uitsluiten¶
De methoden model_dump
en model_dump_json
ondersteunen include
en exclude
van argumenten die sets of woordenboeken kunnen zijn. Hierdoor is een geneste selectie mogelijk van welke velden moeten worden geëxporteerd:
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.model_dump(exclude={'user', 'value'}))
#> {'id': '1234567890'}
# using a dict:
print(t.model_dump(exclude={'user': {'username', 'password'}, 'value': True}))
#> {'id': '1234567890', 'user': {'id': 42}}
print(t.model_dump(include={'id': True, 'user': {'id'}}))
#> {'id': '1234567890', 'user': {'id': 42}}
De True
geeft aan dat we een hele sleutel willen uitsluiten of opnemen, net alsof we deze in een set zouden opnemen. Dit kan op elk diepteniveau.
Er moet speciale aandacht worden besteed aan het opnemen of uitsluiten van velden uit een lijst of tupel submodellen of woordenboeken. In dit scenario verwachten model_dump
en gerelateerde methoden gehele sleutels voor elementgewijze opname of uitsluiting. Om een veld uit te sluiten van elk lid van een lijst of tupel, kan de woordenboeksleutel '__all__'
worden gebruikt, zoals hier weergegeven:
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.model_dump(exclude=exclude_keys) in this case:
print(user.model_dump(include=include_keys))
"""
{
'first_name': 'John',
'address': {'country': {'name': 'USA'}},
'hobbies': [
{'name': 'Programming', 'info': 'Writing code and stuff'},
{'name': 'Gaming'},
],
}
"""
# To exclude a field from all members of a nested list or tuple, use "__all__":
print(user.model_dump(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'}],
}
"""
Hetzelfde geldt voor de model_dump_json
methode.
Inclusief en exclusief op model- en veldniveau¶
Naast de expliciete argumenten exclude
en include
die worden doorgegeven aan de methoden model_dump
en model_dump_json
, kunnen we ook de argumenten exclude: bool
rechtstreeks doorgeven aan de Field
:
Het instellen van exclude
op de veldconstructor ( Field(..., exclude=True)
) heeft voorrang op het exclude
/ include
op model_dump
en model_dump_json
:
from pydantic import BaseModel, Field, SecretStr
class User(BaseModel):
id: int
username: str
password: SecretStr = Field(..., exclude=True)
class Transaction(BaseModel):
id: str
value: int = Field(exclude=True)
t = Transaction(
id='1234567890',
value=9876543210,
)
print(t.model_dump())
#> {'id': '1234567890'}
print(t.model_dump(include={'id': True, 'value': True})) # (1)!
#> {'id': '1234567890'}
value
uitgesloten van de uitvoer omdat deze is uitgesloten inField
.
Dat gezegd hebbende, heeft het instellen van exclude
op de veldconstructor ( Field(..., exclude=True)
) geen prioriteit boven de parameters exclude_unset
, exclude_none
en exclude_default
op model_dump
en model_dump_json
:
from typing import Optional
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str
age: Optional[int] = Field(None, exclude=False)
person = Person(name='Jeremy')
print(person.model_dump())
#> {'name': 'Jeremy', 'age': None}
print(person.model_dump(exclude_none=True)) # (1)!
#> {'name': 'Jeremy'}
print(person.model_dump(exclude_unset=True)) # (2)!
#> {'name': 'Jeremy'}
print(person.model_dump(exclude_defaults=True)) # (3)!
#> {'name': 'Jeremy'}
age
uitgesloten van de uitvoer omdatexclude_none
is ingesteld opTrue
enage
opNone
is.age
uitgesloten van de uitvoer omdatexclude_unset
was ingesteld opTrue
enage
niet was ingesteld in de Person-constructor.age
uitgesloten van de uitvoer omdatexclude_defaults
is ingesteld opTrue
enage
de standaardwaardeNone
heeft.
Serialisatiecontext¶
U kunt een contextobject doorgeven aan de serialisatiemethoden die toegankelijk zijn via het info
argument voor gedecoreerde serialisatiefuncties. Dit is handig wanneer u het serialisatiegedrag tijdens runtime dynamisch moet bijwerken. Als u bijvoorbeeld wilt dat een veld wordt gedumpt op basis van een dynamisch bestuurbare set toegestane waarden, kunt u dit doen door de toegestane waarden per context door te geven:
from pydantic import BaseModel, SerializationInfo, field_serializer
class Model(BaseModel):
text: str
@field_serializer('text')
def remove_stopwords(self, v: str, info: SerializationInfo):
context = info.context
if context:
stopwords = context.get('stopwords', set())
v = ' '.join(w for w in v.split() if w.lower() not in stopwords)
return v
model = Model.model_construct(**{'text': 'This is an example document'})
print(model.model_dump()) # no context
#> {'text': 'This is an example document'}
print(model.model_dump(context={'stopwords': ['this', 'is', 'an']}))
#> {'text': 'example document'}
print(model.model_dump(context={'stopwords': ['document']}))
#> {'text': 'This is an example'}
Op dezelfde manier kunt u een context gebruiken voor validatie .
model_copy(...)
¶
??? api "API-documentatie" pydantic.main.BaseModel.model_copy
model_copy()
maakt het dupliceren van modellen mogelijk (met optionele updates), wat vooral handig is bij het werken met bevroren modellen.
Voorbeeld:
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})
print(m.model_copy(update={'banana': 0}))
#> banana=0 foo='hello' bar=BarModel(whatever=123)
print(id(m.bar) == id(m.model_copy().bar))
#> True
# normal copy gives the same object reference for bar
print(id(m.bar) == id(m.model_copy(deep=True).bar))
#> False
# deep copy gives a new object reference for `bar`
本文总阅读量次