diff --git a/dacite/core.py b/dacite/core.py index fa9e218..b8683c1 100644 --- a/dacite/core.py +++ b/dacite/core.py @@ -89,6 +89,8 @@ def _build_value(type_: Type, data: Any, config: Config) -> Any: elif is_generic_collection(type_) and is_instance(data, extract_origin_collection(type_)): return _build_value_for_collection(collection=type_, data=data, config=config) elif is_dataclass(type_) and is_instance(data, Data): + if hasattr(type_, "from_dict"): + return type_.from_dict(data_class=type_, data=data, config=config) return from_dict(data_class=type_, data=data, config=config) return data diff --git a/tests/core/test_config.py b/tests/core/test_config.py index dc3f187..dc888fc 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from datetime import date from enum import Enum from typing import Optional, List, Union @@ -203,3 +204,35 @@ class Z: result = from_dict(Z, data, Config(strict_unions_match=True)) assert result == Z(u=Y(f=1)) + + +def test_custom_from_dict_in_nested_data_class(): + @dataclass + class X: + d: date + t: str + + def from_dict(data_class, data, config): + data["t"] = "prefix {}".format(data["t"]) + return from_dict( + data_class=data_class, + data=data, + config=Config(type_hooks={date: date.fromtimestamp}), + ) + + @dataclass + class Y: + d: date + x: X + + config = Config(type_hooks={date: date.fromordinal}) + data = {"d": 737790, "x": {"d": 1607511900.985121, "t": "abc"}} + result = from_dict(Y, data, config=config) + + assert result == Y( + d=date(2020, 12, 31), + x=X( + d=date(2020, 12, 9), + t="prefix abc", + ), + )