Configuration on Pydantic dataclasses
Pydantic dataclasses support configuration via the config parameter in the @dataclass decorator. The config parameter accepts a ConfigDict. Example: @dataclass(config=ConfigDict(str_max_length=10, validate_assignment=True)) class User: name: str
Configuration on standard library dataclasses via __pydantic_config__
Standard library dataclasses can be configured using the __pydantic_config__ class attribute, which accepts a ConfigDict. Example: @dataclass class User: __pydantic_config__ = ConfigDict(strict=True); id: int; name: str = 'John Doe'
Pydantic dataclasses provide validation without BaseModel
Pydantic dataclasses offer the same data validation as BaseModel but using standard dataclasses. You can use @pydantic.dataclasses.dataclass decorator to add validation to dataclass fields. Unlike BaseModel, Pydantic dataclasses are not a replacement for models and have different capabilities.
Pydantic dataclass example with validation
from datetime import datetime
from pydantic.dataclasses import dataclass
@dataclass
class User:
id: int
name: str = 'John Doe'
signup_ts: datetime | None = None
user = User(id='42', signup_ts='2032-06-21T12:00')
print(user)
# User(id=42, name='John Doe', signup_ts=datetime.datetime(2032, 6, 21, 12, 0))
This example shows that Pydantic dataclasses coerce string '42' to int and parse datetime strings.
Pydantic dataclass lacks model methods and uses TypeAdapter instead
Pydantic dataclasses do not have the various methods for validation, dumping, and JSON Schema generation that BaseModel provides. Instead, you must wrap the dataclass with TypeAdapter to access methods like dump_python() and validate_python().
Validators work with Pydantic dataclasses
Pydantic dataclasses support field validators using @field_validator decorator, just like models. Validators are applied during dataclass initialization.
Field validator example in dataclass
from pydantic import field_validator
from pydantic.dataclasses import dataclass
@dataclass
class DemoDataclass:
product_id: str # should be a five-digit string, may have leading zeros
@field_validator('product_id', mode='before')
@classmethod
def convert_int_serial(cls, v):
if isinstance(v, int):
v = str(v).zfill(5)
return v
print(DemoDataclass(product_id='01234')) # DemoDataclass(product_id='01234')
print(DemoDataclass(product_id=2468)) # DemoDataclass(product_id='02468')
This example demonstrates using a field validator with mode='before' to convert integers to zero-padded strings.
Dataclass config parameter and __pydantic_config__ attribute
Pydantic dataclass configuration can be set in two ways: (1) using the config parameter of the @dataclass decorator, e.g., @dataclass(config=ConfigDict(validate_assignment=True)), or (2) defining __pydantic_config__ attribute on the class. Unlike BaseModel, dataclasses do not support the model_config attribute.
Dataclass config option examples
from pydantic import ConfigDict
from pydantic.dataclasses import dataclass
# Option 1 -- using the decorator argument:
@dataclass(config=ConfigDict(validate_assignment=True))
class MyDataclass1:
a: int
# Option 2 -- using an attribute:
@dataclass
class MyDataclass2:
a: int
__pydantic_config__ = ConfigDict(validate_assignment=True)
Both approaches enable the same configuration options for dataclasses.
Extra data handling difference in Pydantic dataclasses
Pydantic dataclasses handle extra data differently from models: extra data is not included in serialization. There is no way to customize validation of extra values using the __pydantic_extra__ attribute as with models.
Generic Pydantic dataclasses do not perform type validation
Unlike generic Pydantic models, parameterized generic dataclasses like Foo[int] do not perform validation. A generic dataclass parameterized at instantiation (Foo[int](f='not_an_int')) will not validate the field type and will accept the wrong type. To work around this, wrap the parameterized class with TypeAdapter.
Pydantic dataclass inheriting from stdlib dataclass
Stdlib dataclasses can be inherited by Pydantic dataclasses, and Pydantic will automatically validate all inherited fields. This allows mixing standard library and Pydantic dataclasses in an inheritance hierarchy.
Inheriting from stdlib dataclass example
import dataclasses
import pydantic
@dataclasses.dataclass
class Z:
z: int
@dataclasses.dataclass
class Y(Z):
y: int = 0
@pydantic.dataclasses.dataclass
class X(Y):
x: int = 0
foo = X(x=b'1', y='2', z='3')
print(foo) # X(z=3, y=2, x=1)
try:
X(z='pika')
except pydantic.ValidationError as e:
print(e) # ValidationError: Input should be a valid integer, unable to parse string as an integer
This example shows Pydantic validation being applied to fields from inherited stdlib dataclasses.
Applying dataclass decorator to stdlib dataclass
The @pydantic.dataclasses.dataclass decorator can be applied directly to an existing stdlib dataclass, in which case a new subclass will be created with Pydantic validation added.
Decorator on stdlib dataclass example
import dataclasses
import pydantic
@dataclasses.dataclass
class A:
a: int
PydanticA = pydantic.dataclasses.dataclass(A)
print(PydanticA(a='1')) # A(a=1)
This example shows applying the Pydantic dataclass decorator to an existing stdlib dataclass to create a new Pydantic-validated version.
Stdlib dataclass validation within BaseModel
When a standard library dataclass is used as a field annotation in a Pydantic model or TypeAdapter, validation is applied automatically. Using a stdlib dataclass as a field annotation is functionally equivalent to using a Pydantic dataclass.
Checking if a dataclass is a Pydantic dataclass
Use pydantic.dataclasses.is_pydantic_dataclass() to check if a type is specifically a Pydantic dataclass. The stdlib dataclasses.is_dataclass() function returns True for both stdlib and Pydantic dataclasses.
is_pydantic_dataclass check example
import dataclasses
import pydantic
@dataclasses.dataclass
class StdLibDataclass:
id: int
PydanticDataclass = pydantic.dataclasses.dataclass(StdLibDataclass)
print(dataclasses.is_dataclass(StdLibDataclass)) # True
print(pydantic.dataclasses.is_pydantic_dataclass(StdLibDataclass)) # False
print(dataclasses.is_dataclass(PydanticDataclass)) # True
print(pydantic.dataclasses.is_pydantic_dataclass(PydanticDataclass)) # True
This example demonstrates distinguishing between stdlib and Pydantic dataclasses.
Dataclass __post_init__ method execution order
The dataclass __post_init__() method is supported and will be called between the calls to 'before' and 'after' model validators. For 'before' mode validators, the values parameter is of type ArgsKwargs (not a dict).
__post_init__ and model validator execution order example
from pydantic_core import ArgsKwargs
from typing_extensions import Self
from pydantic import model_validator
from pydantic.dataclasses import dataclass
@dataclass
class Birth:
year: int
month: int
day: int
@dataclass
class User:
birth: Birth
@model_validator(mode='before')
@classmethod
def before(cls, values: ArgsKwargs) -> ArgsKwargs:
print(f'First: {values}') # First: ArgsKwargs((), {'birth': {'year': 1995, 'month': 3, 'day': 2}})
return values
@model_validator(mode='after')
def after(self) -> Self:
print(f'Third: {self}') # Third: User(birth=Birth(year=1995, month=3, day=2))
return self
def __post_init__(self):
print(f'Second: {self.birth}') # Second: Birth(year=1995, month=3, day=2)
user = User(**{'birth': {'year': 1995, 'month': 3, 'day': 2}})
This example shows the execution order: before validator → __post_init__ → after validator. Note that 'before' mode validator receives ArgsKwargs, not a dict.
Dataclass field parameters
Some Field() parameters work with dataclasses: init (whether the field is in the synthesized __init__), init_var (whether the field is init-only), and kw_only (whether the field is keyword-only in the constructor). Init-only fields are not included in serialized output.