|
| 1 | +# Extending pyserde |
| 2 | + |
| 3 | +pyserde はビルトイン型以外をサポートするために pyserde を拡張する 3 つの方法を提供しています。 |
| 4 | + |
| 5 | +## カスタムフィールド(デ)シリアライザ |
| 6 | + |
| 7 | +詳細は[カスタムフィールドシリアライザ](./field-attributes.md#serializerdeserializer)を参照してください。 |
| 8 | + |
| 9 | +> 💡 ヒント:`serde.field` を独自のフィールド関数でラップすると以下のようになります。 |
| 10 | +> |
| 11 | +> ```python |
| 12 | +> import serde |
| 13 | +> |
| 14 | +> def field(*args, **kwargs): |
| 15 | +> serde.field(*args, **kwargs, serializer=str) |
| 16 | +> |
| 17 | +> @serde |
| 18 | +> class Foo: |
| 19 | +> a: int = field(default=0) # フィールドシリアライザの設定 |
| 20 | +> ``` |
| 21 | +
|
| 22 | +## カスタムクラス(デ)シリアライザ |
| 23 | +
|
| 24 | +詳細は[カスタムクラスシリアライザ](./class-attributes.md#class_serializer--class_deserializer)を参照してください。 |
| 25 | +
|
| 26 | +## カスタムグローバル(デ)シリアライザ |
| 27 | +
|
| 28 | +`add_serializer` と `add_deserializer` を使ってクラス(デ)シリアライザを登録することで、コードベース全体でカスタム(デ)シリアライザを適用できます。 |
| 29 | +
|
| 30 | +登録されたクラス(デ)シリアライザは pyserde のグローバル空間にスタックされ、すべての pyserde クラスで自動的に使用されます。 |
| 31 | +
|
| 32 | +例:[isodate](https://pypi.org/project/isodate/)パッケージを使用して `datetime.timedelta` のカスタム(デ)シリアライザを実装する。 |
| 33 | +
|
| 34 | +以下は、`datetime.timedelta` のためのクラス(デ)シリアライザを登録するコードです。 |
| 35 | +このパッケージは実際に PyPI で [pyserde-timedelta](https://pypi.org/project/pyserde-timedelta/) として公開されています。 |
| 36 | +
|
| 37 | +```python |
| 38 | +from datetime import timedelta |
| 39 | +from plum import dispatch |
| 40 | +from typing import Type, Any |
| 41 | +import isodate |
| 42 | +import serde |
| 43 | +
|
| 44 | +class Serializer: |
| 45 | + @dispatch |
| 46 | + def serialize(self, value: timedelta) -> Any: |
| 47 | + return isodate.duration_isoformat(value) |
| 48 | +
|
| 49 | +class Deserializer: |
| 50 | + @dispatch |
| 51 | + def deserialize(self, cls: Type[timedelta], value: Any) -> timedelta: |
| 52 | + return isodate.parse_duration(value) |
| 53 | +
|
| 54 | +def init() -> None: |
| 55 | + serde.add_serializer(Serializer()) |
| 56 | + serde.add_deserializer(Deserializer()) |
| 57 | +``` |
| 58 | +
|
| 59 | +このパッケージの利用者は、 `serde_timedelta.init()` を呼び出すだけで `datetime.timedelta` のカスタム(デ)シリアライザの機能を再利用できます。 |
| 60 | +
|
| 61 | +```python |
| 62 | +import serde_timedelta |
| 63 | +from serde import serde |
| 64 | +from serde.json import to_json, from_json |
| 65 | +from datetime import timedelta |
| 66 | +
|
| 67 | +serde_timedelta.init() |
| 68 | +
|
| 69 | +@serde |
| 70 | +class Foo: |
| 71 | + a: timedelta |
| 72 | +
|
| 73 | +f = Foo(timedelta(hours=10)) |
| 74 | +json = to_json(f) |
| 75 | +print(json) |
| 76 | +print(from_json(Foo, json)) |
| 77 | +``` |
| 78 | +
|
| 79 | +以下のように `datetime.timedelta` がISO 8601 形式でシリアライズされます! |
| 80 | +
|
| 81 | +```bash |
| 82 | +{"a":"PT10H"} |
| 83 | +Foo(a=datetime.timedelta(seconds=36000)) |
| 84 | +``` |
| 85 | +
|
| 86 | +> 💡 ヒント:クラス(デ)シリアライザはいくつでも登録できます。これは、好きなだけpyserde拡張を使用できることを意味します。 |
| 87 | +> 登録された(デ)シリアライザはメモリにスタックされます。 |
| 88 | +> |
| 89 | +> なお、1つの(デ)シリアライザは他の(デ)シリアライザによってオーバーライドされる可能性があります。 |
| 90 | +> |
| 91 | +> 例:次の順序で3つのカスタムシリアライザを登録すると、最初のシリアライザは3番目によって完全に上書きされます。2番目は異なる型用に実装されているため機能します。 |
| 92 | +> |
| 93 | +> 1. `int` 用のシリアライザを登録 |
| 94 | +> 2. `float` 用のシリアライザを登録 |
| 95 | +> 3. `int` 用のシリアライザを登録 |
| 96 | +
|
| 97 | +こちらは、v0.13.0 で新しく追加されました。 |
0 commit comments