Skip to content

Commit 854f0ac

Browse files
authored
Merge pull request #559 from K-dash/translate-union-en-to-ja
Translate union.md to Japanese
2 parents 97bdd0d + e25f484 commit 854f0ac

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

docs/ja/union.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Union Representation
2+
3+
`pyserde>=0.7` では、Union が(デ)シリアライズされる方法を制御するための属性が提供されています。この概念は [serde-rs](https://serde.rs/enum-representations.html) にあるものと同じです。
4+
5+
これらの表現は dataclass にのみ適用され、dataclassではないオブジェクトは常に `Untagged` で(デ)シリアライズされます。
6+
7+
## `Untagged`
8+
9+
以下は、 `pyserde<0.7` におけるデフォルトの Union 表現です。dataclass が与えられた場合を例に上げます。
10+
11+
```python
12+
@serde
13+
class Bar:
14+
b: int
15+
16+
@serde
17+
class Baz:
18+
b: int
19+
20+
@serde(tagging=Untagged)
21+
class Foo:
22+
a: Union[Bar, Baz]
23+
```
24+
25+
注意点として、`Bar``Baz` は同じフィールド名と型を持っています。
26+
`Foo(Baz(10))` を辞書にシリアライズすると、`{"a": {"b": 10}}` が得られます。
27+
28+
しかし、`{"a": {"b": 10}}` をデシリアライズすると、 `Foo(Baz(10))` ではなく `Foo(Bar(10))` が得られます。
29+
これは、pyserde が `Untagged` を使った Union の dataclass を正しく(デ)シリアライズ**できない**ことを意味します。
30+
31+
このため、pyserde は他の Union 表現オプションを提供しています。
32+
33+
## `ExternalTagging`
34+
35+
これは 0.7 以降のデフォルトの Union 表現です。`ExternalTagging` を使用したクラス宣言は以下のようになります。
36+
37+
```python
38+
@serde(tagging=ExternalTagging)
39+
class Foo:
40+
a: Union[Bar, Baz]
41+
```
42+
`Foo(Baz(10))` を辞書にシリアライズすると、 `{"a": {"Baz": {"b": 10}}}` が得られ、デシリアライズすると `Foo(Baz(10))` になります。
43+
44+
> **注意:** dataclass でないオブジェクトは、`tagging` 属性に関わらず常に `Untagged` で(デ)シリアライズされます。
45+
> これはタグに使用できる情報がないためです。`Untagged` の欠点は、特定のタイプを正しく非シリアライズできないことです。
46+
>
47+
> 例えば、以下のクラスの `Foo({1, 2, 3})``{"a": [1, 2, 3]}` にシリアライズされますが、デシリアライズすると `Foo([1, 2, 3])` になります。
48+
>
49+
> ```python
50+
> @serde(tagging=ExternalTagging)
51+
> class Foo:
52+
> a: Union[list[int], set[int]]
53+
> ```
54+
55+
## `InternalTagging`
56+
57+
`InternalTagging` を使用したクラス宣言は以下のようになります。
58+
59+
```python
60+
@serde(tagging=InternalTagging("type"))
61+
class Foo:
62+
a: Union[Bar, Baz]
63+
```
64+
65+
`Foo(Baz(10))` を辞書にシリアライズすると、`{"a": {"type": "Baz", "b": 10}}` が得られ、それを `Foo(Baz(10))` にデシリアライズできます。
66+
`type` タグは `Baz` の辞書内にエンコードされます。
67+
68+
## `AdjacentTagging`
69+
70+
`AdjacentTagging` を使用したクラス宣言は以下のようになります。
71+
72+
```python
73+
@serde(tagging=AdjacentTagging("type", "content"))
74+
class Foo:
75+
a: Union[Bar, Baz]
76+
```
77+
78+
`Foo(Baz(10))` を辞書にシリアライズすると、`{"a": {"type": "Baz", "content": {"b": 10}}}` が得られ、それを `Foo(Baz(10))` にデシリアライズできます。`type` タグは `Baz` の辞書内にエンコードされ、`Baz` のフィールドは `content` 内にエンコードされます。
79+
80+
81+
## Union 型の直接的な(デ)シリアライズ
82+
83+
v0.12.0 で新しく追加されました。
84+
85+
v0.12 以前において、(デ)シリアライズ API(例: `to_json`, `from_json`)に直接 Union 型のデータを渡すことは部分的にサポートされていましたが、Union 型は常にタグ無しとして扱われました。
86+
これは、利用者側で Union タグを変更することができなかったことを意味します。
87+
88+
以下の例は、タグ無しのため `Bar` に正しくデシリアライズできません。
89+
90+
```python
91+
@serde
92+
class Foo:
93+
a: int
94+
95+
@serde
96+
class Bar:
97+
a: int
98+
99+
bar = Bar(10)
100+
s = to_json(bar)
101+
print(s)
102+
# {"a": 10} を出力
103+
print(from_json(Union[Foo, Bar], s))
104+
# Foo(10) を出力
105+
```
106+
107+
v0.12.0 以降、pyserde は(デ)シリアライズ API で渡された Union 型を適切に扱えます。
108+
Union 型は、pyserde のデフォルトのタグ付けである外部タグ付けとして扱われます。
109+
110+
以下の例は `Bar` として正しく(デ)シリアライズできます。
111+
112+
```python
113+
@serde
114+
class Foo:
115+
a: int
116+
117+
@serde
118+
class Bar:
119+
a: int
120+
121+
bar = Bar(10)
122+
s = to_json(bar, cls=Union[Foo, Bar])
123+
print(s)
124+
# {"Bar" {"a": 10}} を出力
125+
print(from_json(Union[Foo, Bar], s))
126+
# Bar(10) を出力
127+
```
128+
129+
また、`serde.InternalTagging``serde.AdjacentTagging`、および `serde.Untagged` を使用してタグ付けを変更できます。
130+
131+
それでは、上記の例を用いてタグ付けを変更してみましょう。
132+
133+
タグ付けを変更するには、 `to_json` に新しい引数 `cls` を渡す必要があります。
134+
また、Unionクラスは `InternalTagging``AdjacentTagging`、または `Untagged` で必要なパラメータと共にラップされる必要があります。
135+
136+
* InternalTagging
137+
```python
138+
from serde import InternalTagging
139+
140+
s = to_json(bar, cls=InternalTagging("type", Union[Foo, Bar]))
141+
print(s)
142+
# {"type": "Bar", "a": 10} を出力
143+
print(from_json(InternalTagging("type", Union[Foo, Bar]), s))
144+
# Bar(10) を出力
145+
```
146+
147+
* AdjacentTagging
148+
```python
149+
from serde
150+
151+
s = to_json(bar, cls=AdjacentTagging("type", "content", Union[Foo, Bar]))
152+
print(s)
153+
# {"type": "Bar", "content": {"a": 10}} を出力
154+
print(from_json(AdjacentTagging("type", "content", Union[Foo, Bar]), s))
155+
# Bar(10) を出力
156+
```
157+
158+
* Untagged
159+
```python
160+
from serde import Untagged
161+
162+
s = to_json(bar, cls=Untagged(Union[Foo, Bar]))
163+
print(s)
164+
# {"a": 10} を出力
165+
print(from_json(Untagged(Union[Foo, Bar]), s))
166+
# Foo(10) を出力
167+
```

0 commit comments

Comments
 (0)