lidatong / dataclasses-json

Easily serialize Data Classes to and from JSON
MIT License
1.34k stars 150 forks source link

decoding optional decimal fields #514

Open rsarili opened 5 months ago

rsarili commented 5 months ago

I have following class with optional Decimal Field with default value None, I got TypeError: conversion from FieldInfo to Decimal is not supported

Is this a bug or should I use different way to define optional Decimal Field with default None value

dataclasses-json version 0.6.3 is used

@dataclass_json
@dataclass
class TestClass:
    price: Decimal
    price_optional: Optional[Decimal] = Field(default=None)

def test_decoder():
    data = TestClass.from_json('{"price": "123.45"}')
    assert data.price == Decimal("123.45")

full error log

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.env/lib/python3.10/site-packages/dataclasses_json/api.py:63: in from_json
    return cls.from_dict(kvs, infer_missing=infer_missing)
.env/lib/python3.10/site-packages/dataclasses_json/api.py:70: in from_dict
    return _decode_dataclass(cls, kvs, infer_missing)
.env/lib/python3.10/site-packages/dataclasses_json/core.py:220: in _decode_dataclass
    init_kwargs[field.name] = _decode_generic(field_type,
.env/lib/python3.10/site-packages/dataclasses_json/core.py:313: in _decode_generic
    res = _support_extended_types(type_arg, value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

field_type = <class 'decimal.Decimal'>
field_value = FieldInfo(annotation=Union[Decimal, NoneType], required=False)

    def _support_extended_types(field_type, field_value):
        if _issubclass_safe(field_type, datetime):
            # FIXME this is a hack to deal with mm already decoding
            # the issue is we want to leverage mm fields' missing argument
            # but need this for the object creation hook
            if isinstance(field_value, datetime):
                res = field_value
            else:
                tz = datetime.now(timezone.utc).astimezone().tzinfo
                res = datetime.fromtimestamp(field_value, tz=tz)
        elif _issubclass_safe(field_type, Decimal):
            res = (field_value
                   if isinstance(field_value, Decimal)
>                  else Decimal(field_value))
E           TypeError: conversion from FieldInfo to Decimal is not supported

.env/lib/python3.10/site-packages/dataclasses_json/core.py:243: TypeError