konradhalas / dacite

Simple creation of data classes from dictionaries.
MIT License
1.72k stars 106 forks source link

support non-dataclass types for the root object passed to from_dict #197

Closed martinResearch closed 1 year ago

martinResearch commented 1 year ago

Thank you for this great tool.

I would like to be able to provide to from_dict a type that is not a dataclass but a more generic type like collection of a dataclass, for example:

from dataclasses import dataclass
from dacite import from_dict
from typing import List

@dataclass
class User:
    name: str
    age: int

data = [
    {
        'name': 'John',
        'age': 30,
    },
    {
        'name': 'Ben',
        'age': 20,
    }
]

users = from_dict(type=List[User], data=data)

I can obviously do

users = [from_dict(data_class=User, data=d) for d in data]

but this much less convenient in the general case.

Because collections are already handled as attributes and because nested dataclasses are handled as well, it seems like this feature would not be too difficult to add, at which point from_dict would be a more generic deserializer than now by not being specific to nested structures whose root is a dataclass anymore. Are there potential technical difficulties to implement this feature?

martinResearch commented 1 year ago

one solution that seems to work is to add in core.py a new function

T = TypeVar("T")

def deserialize(type: Type[T], data: Data, config: Optional[Config] = None) -> T:
    config = config or Config()
    transformed_value = transform_value(
        type_hooks=config.type_hooks, cast=config.cast, target_type=type, value=data
    )
    value = _build_value(type_=type, data=transformed_value, config=config)
    return value
konradhalas commented 1 year ago

@martinResearch thank you for reporting this issue.

Are there potential technical difficulties to implement this feature?

No, I don't see any potential technical obstacles. I just want to keep interface of this library as simple as possible. As you said, you can always iterate on your own and call from_dict multiple times. This is the recommended solution.