環境
- Python3.10.2
- dataclasses-json 0.5.7
何が起きた?
dataclasses-json
のfrom_dict
関数で、Dict型のプロパティに文字列を設定しようとすると、当たり前ですがエラーが発生します。
bar.py
from dataclasses import dataclass
from dataclasses_json import dataclass_json
from typing import List, Dict, Any
@dataclass_json
@dataclass
class Person:
name: str
type: Dict[str, Any]
"""型が間違っている。正しくは`str`型"""
@dataclass_json
@dataclass
class School:
name: str
people: List[Person]
d_person = {"name": "Alice", "type": "junior"}
d_school = {"name": "tokyo", "people": [d_person]}
school = School.from_dict(d_school)
print(school)
vagrant@example:~/Documents/study/python$ python bar.py
Traceback (most recent call last):
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 263, in _decode_generic
res = _get_type_cons(type_)(xs)
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 317, in <genexpr>
items = (_decode_dataclass(type_arg, x, infer_missing)
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 201, in _decode_dataclass
init_kwargs[field.name] = _decode_generic(field_type,
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 254, in _decode_generic
ks = _decode_dict_keys(k_type, value.keys(), infer_missing)
AttributeError: 'str' object has no attribute 'keys'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/vagrant/Documents/study/python/bar.py", line 24, in <module>
school = School.from_dict(d_school)
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/api.py", line 72, in from_dict
return _decode_dataclass(cls, kvs, infer_missing)
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 201, in _decode_dataclass
init_kwargs[field.name] = _decode_generic(field_type,
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/dataclasses_json/core.py", line 265, in _decode_generic
res = type_(xs)
File "/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/typing.py", line 941, in __call__
raise TypeError(f"Type {self._name} cannot be instantiated; "
TypeError: Type List cannot be instantiated; use list() instead
直背的なエラーはAttributeError
なのですが、間接的にTypeError
も発生しました。
これは、dataclasses_json/core.py
のtype_(xs)
で、typing.List(...)
を実行しているためです。
なお、"Type List cannot be instantiated; use list() instead"のメッセージに従って、people
の型をtyping.List[Person]
からlist[Person]
に変更すると、エラーは発生しません。
$ python ~/Documents/study/python/bar.py
School(name='tokyo', people=[])
ただし、people
の値は空リストになります。これは正しくありません。またエラーが発生しないので、間違っていることにも気付けません。
補足
School.from_dict
ではなくSchool.schema().load
を実行すれば、型が異なるときにValidationError
が発生します。
school = School.schema().load(d_school)
# ValidationError: {'people': {0: {'type': ['Not a valid mapping type.']}}}
型を意識したコードを書く場合は、schema().load
を使った方がよさそうです。