Closed bachorp closed 1 year ago
Hi, thanks for opening the issue—though you did not follow the bug template. Thus, I have to explicitly ask you here:
In your provided reproduction scenario, which of the data classes should be instantiated then? A
or B
? I'm just failing to see the use case of that. Your example contains errors anyway, but let's assume something like this:
@dataclass
class A:
foo: Optional[str]
bar: str
@dataclass
class B:
foo: str
bar: Optional[str]
dacite.from_dict(Union[A, B], {"foo": "a", "bar": "b"})
How can I decide which of the classes to instantiate? The input data is valid for both of them.
Maybe instead of a minimum reproducible example you could describe your particular use case?
How can I decide which of the classes to instantiate? The input data is valid for both of them.
The first to match unless strict_unions_match
is set (as specified here).
Maybe [..] you could describe your particular use case?
I want to parse a Json object constituting an authentication request. Authentication can be done by either (1) an authentication token or (2) a username and password. The corresponding types would look like this.
@dataclass
class AuthByToken:
token: str
@dataclass
class AuthByUsernamePassword:
username: str
password: str
AuthRequest = AuthByToken | AuthByUsernamePassword
Parsing a given request (say {"token": "foo"}
) as follows is not possible.
# Variant 1
dacite.from_dict(AuthRequest, {"token": "foo"}) # Throws 'TypeError'
However, if AuthRequest
is instead nested in another type, it works.
@dataclass
class AuthRequestWrapper:
authRequest: AuthRequest
# Variant 2
dacite.from_dict(AuthRequestWrapper, {"authRequest": {"token": "foo"}}) # This works
Although AuthRequest
itself is not a dataclass, I do not see why we could / should not allow it as a target type.
@bachorp Thanks for providing the example. And why couldn't you just use the AuthRequestWrapper
approach, i.e. nesting it within a separate dataclass? The only argument I see is that it is slightly more elaborate, but that's still just a few keywords more over the union approach, and is a bit more explicit in my opinion.
I am just not convinced this is such a big improvement, when one can simply create a wrapper dataclass to store any union they want, and it's much more explicit that way.
@bachorp Closing the issue, thanks for reporting and hope you've resolved your case this way or another!
A union of dataclasses cannot be used for the parameter
data_class
offrom_dict
. See also https://github.com/konradhalas/dacite/issues/138.Minimal example:
This fails with
TypeError: typing.Union[__main__.A, __main__.B] is not a module, class, method, or function.
Tested with python
3.10.9
, dacite1.7.0
.