Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Dataclass.from_json with Union type fields infers missing fields and fails in the wrong spot #488

Open
pingretispec opened this issue Sep 25, 2023 · 1 comment
Labels
bug Something isn't working

Comments

@pingretispec
Copy link

pingretispec commented Sep 25, 2023

Description

I have a Message json dataclass that has a field namely "record" that can be dataclass Record1, Record2, or Record3.
The code fails trying to infer record with dataclass Record1.

Code snippet that reproduces the issue

@dataclass_json
@DataClass
class Message:
type: MessageType
op: Operation
record: Union[Record1, Record2]

@dataclass_json
@DataClass
class Record1:
id: uuid.UUID
date: datetime.date
count: int

@dataclass_json
@DataClass
class Record2:
id: uuid.UUID
date: datetime.date
qty: int

record = Record2(id='001', date=datetime.date(2022,9,22), qty=10)
message = Message(type=MessageType.COUNT, op=Operation.CREATE, record=record)
msg_json = json.dump(message.to_dict(), json_path)
with open(json_path) as json_f:
msg = Message.from_json(json_f.read())

Describe the results you expected

msg = Message(type="COUNT", op="CREATE", record=Record2(id="001", date=datetime.date(2022,9,22), qty=10))

Python version you are using

python --version 3.10.10

Environment description

dataclasses-json==0.6.0

@pingretispec pingretispec added the bug Something isn't working label Sep 25, 2023
@idbentley
Copy link
Contributor

I was able to reproduce this bug with a few simplifications to the code snippet:

from dataclasses import dataclass
from dataclasses_json import dataclass_json
from typing import Union
import uuid
import json

@dataclass_json
@dataclass
class Record1:
    id: uuid.UUID
    count: int

@dataclass_json
@dataclass
class Record2:
    id: uuid.UUID
    qty: int

@dataclass_json
@dataclass
class Message:
    type: str
    op: str
    record: Union[Record1, Record2]

record = Record2(id=uuid.UUID(int=1), qty=10)
message = Message(type='count', op='create', record=record)
msg_json = json.dumps(message.to_dict())
msg = Message.from_json(msg_json)

Which results in:

dataclasses_json/core.py:325: UserWarning: Failed to decode {'id': '001', 'qty': 10} Union dataclasses.Expected Union to include a matching dataclass and it didn't.
  warnings.warn(
>>> msg
Message(type='count', op='create', record={'id': '001', 'qty': 10})

For @pingretispec I would recommend using the schema as a workaround:

from dataclasses import dataclass
from dataclasses_json import dataclass_json
from typing import Union
import uuid
import json

@dataclass_json
@dataclass
class Record1:
    id: uuid.UUID
    count: int

@dataclass_json
@dataclass
class Record2:
    id: uuid.UUID
    qty: int

@dataclass_json
@dataclass
class Message:
    type: str
    op: str
    record: Union[Record1, Record2]

record = Record2(id=uuid.UUID(int=1), qty=10)
message = Message(type='count', op='create', record=record)
schema = message.schema()
schema_json = schema.dump(message)
msg = schema.load(schema_json)

Which does the encoding and decoding successfully:

>>> msg
Message(type='count', op='create', record=Record2(id=UUID('00000000-0000-0000-0000-000000000001'), qty=10))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants