Dacite
Dacite is a Python library that simplifies the creation of data class instances from dictionaries. It focuses on converting raw dictionary data (e.g., from HTTP requests or databases) into robust, type-hinted dataclass objects, leveraging PEP 557 dataclasses. The library is actively maintained, with version 1.9.2 released recently, and receives regular updates including performance improvements and new feature support like generics, forward references, and unions.
Warnings
- gotcha Dacite is a data-to-object mapping library, not a data validation library. It primarily focuses on converting dictionaries to dataclass instances based on type hints. For robust data validation, it's recommended to combine Dacite with a dedicated validation library.
- gotcha By default, Dacite expects all non-optional fields in the target dataclass to have corresponding keys in the input dictionary. If a required field is missing from the input dictionary and does not have a default value in the dataclass, a `MissingValueError` will be raised.
- gotcha Dacite performs basic type checking but does not automatically coerce types by default (e.g., converting a string '123' to an integer 123 for an `int` field), which can lead to `WrongTypeError`. Automatic casting needs to be explicitly enabled.
- gotcha When using `typing.Union`, Dacite by default tries to find the first matching type. If `Config(strict_unions_match=True)` is used, it will raise a `StrictUnionMatchError` if more than one type in the Union could match the input data.
- gotcha Dacite does not dynamically add fields to dataclasses that are not predefined in the dataclass definition. If your input dictionary contains keys not present in the dataclass, those keys will be ignored during conversion unless `Config(check_types=False)` is used (which is not recommended for type safety).
Install
-
pip install dacite
Imports
- from_dict
from dacite import from_dict
- Config
from dacite import from_dict, Config
Quickstart
from dataclasses import dataclass
from dacite import from_dict, Config
@dataclass
class User:
name: str
age: int
is_active: bool
@dataclass
class Address:
street: str
city: str
@dataclass
class Profile:
user: User
address: Address
preferences: dict
data = {
'user': {'name': 'Jane Doe', 'age': 28, 'is_active': False},
'address': {'street': '123 Main St', 'city': 'Anytown'},
'preferences': {'theme': 'dark', 'notifications': True}
}
# Basic conversion
profile = from_dict(data_class=Profile, data=data)
print(profile)
# Expected: Profile(user=User(name='Jane Doe', age=28, is_active=False), address=Address(street='123 Main St', city='Anytown'), preferences={'theme': 'dark', 'notifications': True})
# Example with a type hook (e.g., converting all strings to uppercase)
@dataclass
class Item:
id: str
value: int
def uppercase_str(s: str) -> str:
return s.upper()
item_data = {'id': 'item-abc', 'value': 100}
config_with_hook = Config(type_hooks={str: uppercase_str})
item = from_dict(data_class=Item, data=item_data, config=config_with_hook)
print(item)
# Expected: Item(id='ITEM-ABC', value=100)