3.3. Pydantic Types Stdlib
Where possible pydantic uses standard library to define fields,
thus smoothing the learning curve. For many useful applications,
however, no standard library type exists, so pydantic implements
many commonly used types.
3.3.1. Standard Library Types
pydantic supports many common types from the python standard library.
If you need stricter processing see Strict Types; if
you need to constrain the values allowed (e.g. to require a positive
int) see Constrained Types.
None - allows only None value
boolsee Booleans below for details on how bools are validated and what values are permitted
int*pydanticusesint(v)to coerce types to anint; see Data Conversion warning on loss of information during data conversionfloatsimilarly,
float(v)is used to coerce values to floatsstrstrings are accepted as-is,
intfloatandDecimalare coerced usingstr(v),bytesandbytearrayare converted usingv.decode(), enums inheriting fromstrare converted usingv.value, and all other types cause an errorbytesbytesare accepted as-is,bytearrayis converted usingbytes(v),strare converted usingv.encode(), andint,float, andDecimalare coerced usingstr(v).encode()listallows
list,tuple,set,frozenset,deque, or generators and casts to a listtupleallows
list,tuple,set,frozenset,deque, or generators and casts to a tupledictdict(v)is used to attempt to convert a dictionarysetallows
list,tuple,set,frozenset,deque, or generators and casts to a setfrozensetallows
list,tuple,set,frozenset,deque, or generators and casts to a frozen setdequeallows
list,tuple,set,frozenset,deque, or generators and casts to a dequedatetime.datesee Datetime Types for more detail on parsing and validation
datetime.timesee Datetime Types for more detail on parsing and validation
datetime.datetimesee Datetime Types for more detail on parsing and validation
datetime.timedeltasee Datetime Types below for more detail on parsing and validation
typing.Anyallows any value including
None, thus anAnyfield is optionaltyping.Annotatedallows wrapping another type with arbitrary metadata, as per PEP 593. The
Annotatedhint may contain a single call to the Field function, but otherwise the additional metadata is ignored and the root type is used.typing.TypeVarconstrains the values allowed based on
constraintsorboundtyping.Unionsee Unions for more detail on parsing and validation
typing.OptionalOptional[x]is simply short hand forUnion[x, None]typing.Listsee Typing Iterables> below for more detail on parsing and validation
typing.Tuplesee Typing Iterables> below for more detail on parsing and validation
subclass of typing.NamedTupleSame as
tuplebut instantiates with the given namedtuple and validates fields since they are annotatedsubclass of collections.namedtupleSame as
subclass of typing.NamedTuplebut all fields will have typeAnysince they are not annotatedtyping.Dictsee Typing Iterables below for more detail on parsing and validation
subclass of typing.TypedDictSame as
dictbutpydanticwill validate the dictionary since keys are annotatedtyping.Setsee Typing Iterables below for more detail on parsing and validation
typing.FrozenSetsee Typing Iterables below for more detail on parsing and validation
typing.Dequesee Typing Iterables below for more detail on parsing and validation
typing.Sequencesee Typing Iterables below for more detail on parsing and validation
typing.Iterablethis is reserved for iterables that shouldn't be consumed
typing.Typesee Type for more detail on parsing and validation
typing.Callablesee Callable for more detail on parsing and validation
typing.Patternwill cause the input value to be passed to
re.compile(v)to create a regex patternipaddress.IPv4Addresssimply uses the type itself for validation by passing the value to
IPv4Address(v)ipaddress.IPv4Interfacesimply uses the type itself for validation by passing the value to
IPv4Address(v)ipaddress.IPv4Networksimply uses the type itself for validation by passing the value to
IPv4Network(v)ipaddress.IPv6Addresssimply uses the type itself for validation by passing the value to
IPv6Address(v)ipaddress.IPv6Interfacesimply uses the type itself for validation by passing the value to
IPv6Interface(v)ipaddress.IPv6Networksimply uses the type itself for validation by passing the value to
IPv6Network(v)enum.Enumchecks that the value is a valid Enum instance
subclass of enum.Enumchecks that the value is a valid member of the enum
enum.IntEnumchecks that the value is a valid IntEnum instance
subclass of enum.IntEnumchecks that the value is a valid member of the integer enum
decimal.Decimalpydanticattempts to convert the value to a string, then passes the string toDecimal(v)pathlib.Pathsimply uses the type itself for validation by passing the value to
Path(v)uuid.UUIDstrings and bytes (converted to strings) are passed to
UUID(v), with a fallback toUUID(bytes=v)forbytesandbytearray;ByteSizeconverts a bytes string with units to bytes
3.3.2. Datetime Types
datetimefieldsdatefieldstimefieldstimedeltafieldshttps://docs.python.org/library/datetime.html#available-types
Pydantic supports the following datetime types
datetimefields can be:datetime, existingdatetimeobjectintorfloat, assumed as Unix time, i.e. seconds (if >=-2e10or <=2e10) or milliseconds (if <-2e10``or > ``2e10) since 1 January 1970str, following formats work:YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]intorfloatas a string (assumed as Unix time)
datefields can be:date, existingdateobjectintorfloat, seedatetimestr, following formats work:YYYY-MM-DDintorfloat, seedatetime
timefields can be:time, existingtimeobjectstr, following formats work:HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
timedeltafields can be:timedelta, existingtimedeltaobjectintorfloat, assumed as secondsstr, following formats work:[-][DD ][HH:MM]SS[.ffffff][±]P[DD]DT[HH]H[MM]M[SS]S(ISO 8601 format for timedelta)
3.3.3. Booleans
A standard bool field will raise a ValidationError if the value is
not one of the following:
A valid boolean (i.e.
TrueorFalse),The integers
0or1,a
strwhich when converted to lower case is one of'0', 'off', 'f', 'false', 'n', 'no', '1', 'on', 't', 'true', 'y', 'yes'a
byteswhich is valid (per the previous rule) when decoded tostr
If you want stricter boolean logic (e.g. a field which only permits True and False) you can
use `StrictBool <#strict-types>`_.
Here is a script demonstrating some of these behaviors:
3.3.4. Callable
Fields can also be of type Callable:
Callable fields only perform a simple check that the argument is callable; no validation of arguments, their types, or the return type is performed.
3.3.5. Type
pydantic supports the use of type[T] to specify that a field may only
accept classes (not instances) that are subclasses of T.
You may also use Type to specify that any class is allowed.
3.3.6. TypeVar
TypeVar is supported either unconstrained, constrained or with a bound.
3.3.7. Literal Type
pydantic supports the use of typing.Literal as a lightweight way to
specify that a field may accept only specific literal values:
One benefit of this field type is that it can be used to check for equality with one or more specific values without needing to declare custom validators:
With proper ordering in an annotated Union, you can use this to parse
types of decreasing specificity:
3.3.8. Annotated Types
3.3.9. NamedTuple
3.3.10. TypedDict
3.3.11. Typing Iterables
pydantic uses standard library typing types as defined in PEP 484
to define complex objects.
3.3.12. Infinite Generators
If you have a generator you can use Sequence as described above. In
that case, the generator will be consumed and stored on the model as a
list and its values will be validated with the sub-type of Sequence
(e.g. int in Sequence[int]).
But if you have a generator that you don't want to be consumed, e.g. an
infinite generator or a remote data loader, you can define its type with
Iterable:
Warning Iterable fields only perform a simple check that the
argument is iterable and won't be consumed. No validation of their values is performed as it cannot be done without consuming the iterable.
If you want to validate the values of an infinite generator you can create a separate model and use it while consuming the generator, reporting the validation errors as appropriate.
pydantic can't validate the values automatically for you because it would require consuming the infinite generator.
3.3.13. Validating the first value
You can create a Validator to validate the first value in an infinite generator and still not consume it entirely.
3.3.14. Unions
The
Uniontype allows a model attribute to accept different types
You may get unexpected coercion with Union; see below. Know
that you can also make the check slower but stricter by using Smart Union.
However, as can be seen above, pydantic will attempt to 'match' any of
the types defined under Union and will use the first one that
matches. In the above example the id of user_03 was defined as a
uuid.UUID class (which is defined under the attribute's Union
annotation) but as the uuid.UUID can be marshalled into an int
it chose to match against the int type and disregarded the other
types.
typing.Union also ignores order when
defined,
so Union[int, float] == Union[float, int] which can lead to
unexpected behaviour when combined with matching based on the Union
type order inside other type definitions, such as List and Dict
types (because python treats these definitions as singletons). For
example,
Dict[str, Union[int, float]] == Dict[str, Union[float, int]] with
the order based on the first time it was defined. Please note that this
can also be affected by third party libraries and their internal type
definitions and the import orders. As such, it is recommended that, when
defining Union annotations, the most specific type is included first
and followed by less specific types.
In the above example, the UUID class should precede the int and
str classes to preclude the unexpected representation as such.
The type Optional[x] is a shorthand for Union[x, None].
Optional[x] can also be used to specify a required field that can
take None as a value.
3.3.15. Discriminated Unions (a.k.a. Tagged Unions)
When Union is used with multiple submodels, you sometimes know
exactly which submodel needs to be checked and validated and want to
enforce this. To do that you can set the same field - let's call it
my_discriminator - in each of the submodels with a discriminated
value, which is one (or many) Literal value(s). For your Union,
you can set the discriminator in its value:
Field(discriminator='my_discriminator').
Setting a discriminated union has many benefits:
validation is faster since it is only attempted against one model
only one explicit error is raised in case of failure
the generated JSON schema implements the associated OpenAPI specification
Using the Annotated Fields syntax can be handy to regroup the Union
and discriminator information.
3.3.16. Nested Discriminated Unions
Only one discriminator can be set for a field but sometimes you want to
combine multiple discriminators. In this case you can always create
"intermediate" models with _root__ and add your discriminator.
3.3.17. Enums and Choices
pydantic uses python's standard enum classes to define choices.
3.3.18. Generic Classes as Types
This is an advanced technique that you might not need in the
beginning. In most of the cases you will probably be fine with standard
pydantic models.
You can use Generic
Classes
as field types and perform custom validation based on the "type
parameters" (or sub-types) with _get_validators__.
If the Generic class that you are using as a sub-type has a classmethod
_get_validators__ you don't need to use arbitrary_types_allowed
for it to work.
Because you can declare validators that receive the current field,
you can extract the sub_fields (from the generic class type
parameters) and validate data with them.