Decorators

@serde

@serde@serialize@deserialize デコレータのラッパーです。

以下のコードがあるとします。

@serde
class Foo:
    ...

上記のコードは、以下のコードと同等です。

@deserialize
@serialize
@dataclass
class Foo:
    ...

@serde デコレータは以下を行います。

  • クラスに @serialize@deserialize デコレータを追加します。
  • クラスが @dataclass を持っていない場合、@dataclass デコレータを追加します。
  • 両方の(デ)シリアライズ属性をデコレータに渡すことができます。
    • serializer 属性は @deserialize で無視され、deserializer 属性は @serialize で無視されます。
@serde(serializer=serializer, deserializer=deserializer)
@dataclass
class Foo:
    ...

注記: @serde@dataclass デコレータなしで動作します。
これはserdeが @dataclass を自動的に検出し、宣言されたクラスに追加するからです。
しかし @dataclass を定義しない場合、mypy では Too many arguments または Unexpected keyword argument というエラーが発生します。これは mypy の制限によるものです。

@serde
class Foo:
    ...

しかし、PEP681に準拠した型チェッカー(例:pyright)を使用すると、pyserdeが PEP681 dataclass_transform をサポートしているため、型エラーは発生しません。

@serialize@deserialize

@serialize および @deserialize は内部的に @serde によって使用されます。
以下に該当する場合、これら2つのデコレータを使用することを推奨します。

  • シリアライズまたはデシリアライズの機能のみが必要な場合
  • 以下のように異なるクラス属性を持つことを望む場合
@deserialize(rename_all = "snakecase")
@serialize(rename_all = "camelcase")
class Foo:
    ...

上記に当てはまらない場合は @serde の使用を推奨します。

@serde なしでクラスを(デ)シリアライズする

pyserdeは v0.10.0 以降、@serde なしでデータクラスを(デ)シリアライズできます。
この機能は、外部ライブラリで宣言されたクラスを使用したい場合や、@serde デコレータが型チェッカーで機能しない場合に便利です。この例を参照してください。

どのように動作するのでしょうか?
それは非常に単純で、クラスが@serdeデコレータを持っていない場合、pyserdeは @serde デコレータを追加します。
最初のAPI呼び出しには時間がかかるかもしれませんが、生成されたコードは内部的にキャッシュされるため問題にはなりません。

以下にサードパーティパッケージのクラスをデシリアライズする例を示します。

@dataclass
class External:
    ...

to_dict(External()) # "@serde" なしで動作します

この場合、rename_all などのクラス属性を指定することはできません。
外部のデータクラスにクラス属性を追加したい場合は、データクラスを拡張することでそれを行う方法があります。この例を参照してください。

@dataclass
class External:
    some_value: int

@serde(rename_all="kebabcase")
@dataclass
class Wrapper(External):
    pass

前方参照をどのように使用するか?

pyserdeは前方参照をサポートしています。
ネストされたクラス名を文字列で置き換えると、pyserdeはネストされたクラスが定義された後にデコレータを探して評価します。

from __future__ import annotations # annotationsをインポート

@dataclass
class Foo:
    i: int
    s: str
    bar: Bar  # "Bar" は後で宣言されていても指定できます

@serde
@dataclass
class Bar:
    f: float
    b: bool

# "Bar" が定義された後に pyserde デコレータを評価します
serde(Foo)

PEP563 Annotationsによる遅延評価

pyserdeは PEP563 Annotationsによる遅延評価をサポートしています。

from __future__ import annotations
from serde import serde

@serde
class Foo:
    i: int
    s: str
    f: float
    b: bool

    def foo(self, cls: Foo):  # 定義される前に "Foo" 型を使用できます
        print('foo')

完全な例については examples/lazy_type_evaluation.py を参照してください。