1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

dataclass-json:`infer_missing=True`を指定すれば、デフォルト値が設定されていないOptionalフィールドの値を推測できる

1
Last updated at Posted at 2022-01-24

実行環境

  • Python 3.9.7
  • dataclasses-json 0.5.6

はじめに

jsonやdictからPythonのデータクラスを生成するために、dataclasses-json を使っています。

以下のように、Animalクラスのdetailフィールドにデフォルト値が設定されている場合、detailキーが存在しないdictからAnimalクラスのインスタンスを生成できます。

@dataclass_json
@dataclass
class Animal:
    name: str
    detail: Optional[str] = None

Animal.from_dict({"name": "dog"})
# Animal(name='dog', detail=None)

問題提起

今、Animalクラスがあります。

@dataclass_json
@dataclass
class Animal:
    name: str
    detail: Optional[str] = None

Animalクラスにtypeという必須フィールドを、後から追加する必要があることが分かりました。
Animal("human", "foo")のように位置引数を指定してAnimalクラスのインスタンスを生成する場合もあるので、Animalクラスのフィールドの順番は変えたくありません。したがって、Animalクラスの最後尾にtypeフィールドを追加してみます。

なんと、最後尾にtypeフィールドを追加すると、TypeErrorが発生しました。デフォルト値を受け取る引数より後ろの引数は、必ずデフォルト値を設定する必要があるためです。

@dataclass_json
@dataclass
class Animal:
    name: str
    detail: Optional[str] = None
    type: str

# TypeError: non-default argument 'type' follows default argument

TypeErrorを回避するため、detailフィールドのデフォルト値を除去しました。これで、Animalクラスは無事定義できました。

@dataclass_json
@dataclass
class Animal:
    name: str
    detail: Optional[str]
    type: str

しかし、デフォルト値が設定されていないため、以下のようにdetailキーが存在しないdictからAnimalクラスのインスタンスを生成できません。これでは不便です。

Animal.from_dict({"name":"human", "type": "Mammal"})

# KeyError: 'detail'

解決策

from_dictメソッドにinfer_missing=Trueを指定すれば、detailキーが存在しないdictからAnimalクラスのインスタンスを生成できます。

Animal.from_dict({"name":"human", "type": "Mammal"},infer_missing=True)
# Animal(name='human', detail=None, type='Mammal')

ただしinfer_missing=Trueを指定すると、Optionalでない型のフィールドが指定されていないときでも、Animalクラスのインスタンスを生成できてしまいます。

Animal.from_dict({"name":"human"}, infer_missing=True)
# RuntimeWarning: Missing value of non-optional type type detected when decoding Animal and was defaulted to None by infer_missing=True. Set infer_missing=False (the default) to prevent this behavior.
# Animal(name='human', detail=None, type=None)

そういった理由のためか、公式サイトではinfer_missing=Trueを指定することより、デフォルト値を設定することを推奨しています。

Personally I recommend you leverage dataclass defaults rather than using infer_missing, but if for some reason you need to decouple the behavior of JSON decoding from the field's default value, this will allow you to do so.

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?