🐷

RustでHashMapを任意の型にDeserializeする

2021/12/24に公開

使いどころがわからないですが、副産物的に知らなかったことを学べたのでメモ程度で置いておきます。隙間時間でRust初めて1ヶ月の初心者なので、書き方におかしい部分などあったらご指摘ください。

概要

  • rustで以下の感じの任意のValueを持つHashMapを、ある型に変換したいと思いました。
// HashMap
{
    para: "hogehoge",
    vec_para: ["hehe1", "hehe2"],
}

// struct
struct MyStruct {
    para: String,
    vec_para: Vec<String>,
}

ハマったこと

  1. 任意の値を持つHashMapを作れない
  2. HashMapを構造体に変換できない

以下どう対処(妥協)したか書いてきます。

対処

1. 任意の値を持つHashMapを作れない

これは悩んだ末、2通り対処を考えました。

  • std::any::Anyを使う
  • enumである程度値の型を限定する

前者だと、serialize/deserializeのためにserde_traitobjectを使う必要がありました。ただ、その際metatypeに#[feature]のものがあり、stable版Rustではだめそうだったので止めました。

結局は後者でenumを作って単値(String)、多値(Vec<String>)のみを受けることにしました。

2. HashMapを構造体に変換できない

これはserdeserde_jsonを使えばすんなりできました。
ただしenumserializeするときにStrとかArrが表示されないように#[serde(untagged)]をつける必要がありました。

ここまででできたもの

Playground

まとめ

何に使うかわからないですが、以下2点は学びでした。

  • serdeuntagged(というかserdeクレートを初めて知った)
  • HashMapに任意の型持たせるときはenumで持たせる(当然)

Discussion