Following this example:
from dataclass_wizard import DataclassWizard
from typing import Dict, Literal
class Test(DataclassWizard):
error: Dict[int | Literal["123"], str]
successful: int | Literal["123"]
Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "123": "4"}, "successful": "1"}')
we've got this exception:
dataclass_wizard.errors.ParseError: Failed to load field `a` in class `A`. Expected a type (<class 'int'>, typing.Literal['123']), got str.
phase: load
value: '1'
error: Object was not in any of Union types
tag_key: __tag__
json_object: {"a": {"1": "1", "2": "2", "3": "3", "123": "4"}, "b": "test"}
but we shouldn't as every key in the Dict is valid
going deeper we can see that the output function is:
def __create__load_Test_union_7f0ed97afcc1_fn__(cls, fields, tag_key, as_int):
def _load_Test_union_7f0ed97afcc1(k2):
tp = type(k2)
if tp is int:
return k2
try:
return _load_literal_093b94741fad(v2)
except Exception:
pass
try:
return v2 if (t := v2.__class__) is int else int(f if '.' in v2 and (f := float(v2)).is_integer() else v2) if t is str else as_int(v2, t, int)
except Exception:
pass
raise ParseError(TypeError('Object was not in any of Union types'),k2,fields,'load',tag_key=tag_key)
return _load_Test_union_7f0ed97afcc1
v2 is used instead of k2 in this function only when a Dict contains a Union
possible fix at:
|
tp_new = TypeInfo(possible_tp, i=i) |
the line should be
tp_new = TypeInfo(possible_tp, i=i, prefix=tp.prefix)
so that the prefix is correctly transmit to the next step
with this fix the output is
def __create__load_Test_union_7f0ed97afcc1_fn__(cls, fields, tag_key, as_int):
def _load_Test_union_7f0ed97afcc1(k2):
tp = type(k2)
if tp is int:
return k2
try:
return _load_literal_093b94741fad(k2)
except Exception:
pass
try:
return k2 if (t := k2.__class__) is int else int(f if '.' in k2 and (f := float(k2)).is_integer() else k2) if t is str else as_int(k2, t, int)
except Exception:
pass
raise ParseError(TypeError('Object was not in any of Union types'),k2,fields,'load',tag_key=tag_key)
return _load_Test_union_7f0ed97afcc1
full final test:
from dataclass_wizard import DataclassWizard
from typing import Dict, Literal
class Test(DataclassWizard):
error: Dict[int | Literal["AAA"], str]
successful: int | Literal["AAA"]
Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "1"}')
Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "AAA"}')
Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "BBB": "4"}, "successful": "1"}')
Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "BBB"}')
result:
>>> Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "1"}')
"2": "2", "3": "3", "AAA": "4"}, "successful": "AAA"}')Test(error={1: '1', 2: '2', 3: '3', 'AAA': '4'}, successful=1)
>>> Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "AAA"}')
Test(error={1: '1', 2: '2', 3: '3', 'AAA': '4'}, successful='AAA')
>>> Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "BBB": "4"}, "successful": "1"}')
dataclass_wizard.errors.ParseError: Failed to load field `error` in class `Test`. Expected a type (<class 'int'>, typing.Literal['AAA']), got str.
phase: load
value: 'BBB'
error: Object was not in any of Union types
tag_key: __tag__
json_object: {"error": {"1": "1", "2": "2", "3": "3", "BBB": "4"}, "successful": "1"}
>>> Test.from_json('{"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "BBB"}')
dataclass_wizard.errors.ParseError: Failed to load field `successful` in class `Test`. Expected a type (<class 'int'>, typing.Literal['AAA']), got str.
phase: load
value: 'BBB'
error: Object was not in any of Union types
tag_key: __tag__
json_object: {"error": {"1": "1", "2": "2", "3": "3", "AAA": "4"}, "successful": "BBB"}
Following this example:
we've got this exception:
but we shouldn't as every key in the Dict is valid
going deeper we can see that the output function is:
v2 is used instead of k2 in this function only when a Dict contains a Union
possible fix at:
dataclass-wizard/dataclass_wizard/v1/loaders.py
Line 570 in 287fa66
the line should be
tp_new = TypeInfo(possible_tp, i=i, prefix=tp.prefix)so that the prefix is correctly transmit to the next step
with this fix the output is
full final test:
result: