Configuration on TypeAdapter
TypeAdapter supports configuration by providing the config argument with a ConfigDict. Example: ta = TypeAdapter(list[str], config=ConfigDict(coerce_numbers_to_str=True)). Configuration cannot be provided if the type adapter directly wraps a type that supports configuration; a usage error is raised in this case.
TypeAdapter methods for dataclass serialization and validation
from pydantic import TypeAdapter
from pydantic.dataclasses import dataclass
@dataclass
class Foo:
f: int
foo = Foo(f=1)
TypeAdapter(Foo).dump_python(foo) # {'f': 1}
TypeAdapter(Foo).validate_python({'f': 1}) # Foo(f=1)
This example shows how to use TypeAdapter with dataclasses to perform serialization and validation.
Instantiate TypeAdapter once and reuse it
To improve performance, avoid constructing TypeAdapter instances repeatedly. Each TypeAdapter instantiation creates new validator and serializer objects. If using TypeAdapter in a function that gets called multiple times, instantiate it once at module level and reuse it across function calls rather than recreating it on each invocation.
TypeAdapter purpose and use cases
TypeAdapter is used for type validation, serialization, and JSON schema generation without needing to create a BaseModel. It is useful when you have types that are not BaseModels that you want to validate data against, such as when validating a list[SomeModel] or dumping it to JSON.
TypeAdapter exposes BaseModel functionality for non-BaseModel types
A TypeAdapter instance exposes some of the functionality from BaseModel instance methods for types that do not have such methods, such as dataclasses, primitive types, TypedDicts, and other Pydantic-compatible types.
TypeAdapter.validate_python method
TypeAdapter has a validate_python method that applies parsing logic to populate data into a specified type. It behaves similarly to BaseModel.model_validate but works with arbitrary Pydantic-compatible types.
TypeAdapter.dump_json returns bytes not str
TypeAdapter's dump_json method returns a bytes object, unlike BaseModel's model_dump_json which returns a str. This is retained for backwards compatibility with V1 behavior. The bytes return type is often the desired end type for TypeAdapter.
TypeAdapter cannot be used as field type annotation
TypeAdapter should not be used as a type annotation for specifying fields of a BaseModel or similar constructs, despite some overlap in use cases with RootModel.
TypeAdapter works with any Pydantic-compatible field type
TypeAdapter is capable of parsing data into any of the types Pydantic can handle as fields of a BaseModel.
TypeAdapter raises structured validation errors
A TypeAdapter raises the same structured errors as a model when validation fails. This allows tooling that records validation failures in production, such as Logfire, to capture these errors.
TypeAdapter schema creation has overhead
When creating an instance of TypeAdapter, the provided type must be analyzed and converted into a pydantic-core schema. This comes with non-trivial overhead, so it is recommended to create a TypeAdapter for a given type just once and reuse it in loops or other performance-critical code.
TypeAdapter defer_build configuration option
When initializing a TypeAdapter, you can set defer_build to True in the ConfigDict to defer building the core schema until the first time it is needed for validation or serialization. This is helpful for types with forward references or types for which core schema builds are expensive.
TypeAdapter.rebuild method
The rebuild method on a TypeAdapter instance can be called to manually trigger the building of the core schema. This is useful after forward references have been defined.
TypeAdapter example with TypedDict validation
```python
from typing_extensions import TypedDict
from pydantic import TypeAdapter, ValidationError
class User(TypedDict):
name: str
id: int
user_list_adapter = TypeAdapter(list[User])
user_list = user_list_adapter.validate_python([{'name': 'Fred', 'id': '3'}])
print(repr(user_list))
#> [{'name': 'Fred', 'id': 3}]
try:
user_list_adapter.validate_python(
[{'name': 'Fred', 'id': 'wrong', 'other': 'no'}]
)
except ValidationError as e:
print(e)
print(repr(user_list_adapter.dump_json(user_list)))
#> b'[{"name":"Fred","id":3}]'
```
This example demonstrates using TypeAdapter to validate a list of TypedDict objects, including type coercion (string '3' to int 3) and JSON serialization to bytes.
TypeAdapter example with BaseModel in list
```python
from pydantic import BaseModel, TypeAdapter
class Item(BaseModel):
id: int
name: str
item_data = [{'id': 1, 'name': 'My Item'}]
items = TypeAdapter(list[Item]).validate_python(item_data)
print(items)
#> [Item(id=1, name='My Item')]
```
This example demonstrates using TypeAdapter to parse data into a list of BaseModel objects without needing to create an explicit model for the list.
TypeAdapter forward reference example with defer_build
```python
from pydantic import ConfigDict, TypeAdapter
ta = TypeAdapter('MyInt', config=ConfigDict(defer_build=True))
# some time later, the forward reference is defined
MyInt = int
ta.rebuild()
assert ta.validate_python(1) == 1
```
This example demonstrates using defer_build to handle forward references and manually rebuilding the schema after the type is defined.