2
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 1 year has passed since last update.

serdeの属性で複数の表現をenumで受け取る

Last updated at Posted at 2022-11-15
1 / 11

serdeでは様々な入力をenumでまとめて扱うことができます。
serdeのマニュアルに載っているので、このリンクを読んだことがあるなら既知の情報が多いかもしれません。

以下のようなMessageをjsonで受け取ることを例として見ていきます。

#[derive(Serialize, Deserialize)]
enum Message {
    A { id: u64, event_code: u64 },
    B { id: u64, message: String },
}

Externaly tagged

何の属性を設定しない、一般的なenumのシリアライズ方法です。
variantの名前をkeyに、中身をvalueに設定します。
期待する入力は以下のようなjsonになります。

{ 
    "A" : {
        "id" : 1,
        "event_code": 4
    }
}

Internally tagged

対象のenumに#[serde(tag = "type")]を付けるとvariantの名前をvalueとして受け取ることができます。keyはtagの後につけた"type"の場所の値になります。

{ 
    "type" : "A",
    "id" : 1,
    "event_code": 4
}

Adjacently tagged

対象のenumに#[serde(tag = "type", content = "message")]を付けると中身もobjectとして受け取ることができます。

{ 
    "type" : "A",
    "message" : {
        "id" : 1,
        "event_code": 4
    }
}

Untagged

対象のenumに#[serde(untagged)]を付けるとtagではなくkeyの種類でenumを変化させます。keyで合致した最初のvariantを返します。

{ 
    "id" : 1,
    "event_code": 4
}

Untaggedの使い方

Untaggedは受け取る型を任意にするために使うことができます。

// 文字列でも数値でも受け取れる型
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Input{
    Str(String),
    Int(i64),
}

比較

ここまではリファレンス通りで寂しいのでいろいろ比較してみました。


expand後のサイズ

まずはcargo expand --releaseしてコードのサイズがどれくらい違うかを比較します。
serdeの属性以外は同じコードにします。
以下のenumで比較します。

enum Message {
    A { id: u64, event_code: u64 },
    B { id: u64, message: String },
}
Externally Internally Adjacently Untagged
行数 759行 750行 1383行 540行
バイト数 40KB 36KB 84KB 25KB

Untaggedが一番多いとの個人的予想を裏切り、Adjacentlyが一番長いという結果に。


ベンチマーク

同様に同じenumでパフォーマンスを比較してみました。
上と同じMessageで比較しました。
cargo criterionでのベンチマークの結果は以下のようになりました。

Externally Internally Adjacently Untagged
Message 69.486 ns 232.36 ns 130.55 ns 141.51 ns

Externallyが早いですがこれくらいのenumならパフォーマンス上大差がないのがわかります。(後で大きなサイズのenumでどれくらい大きくなるかも比較してみたいと思います。)


まとめ

serdeのderiveがいろいろうまくやってくれるのでいろんなjsonの表現からenumを作ることができます。serdeのリファレンスはいろいろ便利な属性が載っているのでぜひご覧ください。

2
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
2
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?