0
0

More than 1 year has passed since last update.

[dataclasses-json] Dict型のプロパティに文字列を設定しようとすると、"TypeError: Type List cannot be instantiated; use list() instead"が発生した

Last updated at Posted at 2022-07-05

環境

  • Python3.10.2
    • dataclasses-json 0.5.7

何が起きた?

dataclasses-jsonfrom_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.pytype_(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を使った方がよさそうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0