7

API から JSON を受信して​​いますが、応答は 30 種類のいずれかになります。各タイプには固有のフィールド セットがありますが、すべての応答には、typeそれがどのタイプであるかを示すフィールドがあります。

私のアプローチはserdeを使用することです。応答タイプごとに構造体を作成し、それらをデコード可能にします。それができたら、新しく受信したメッセージに使用する構造体を選択するにはどうすればよいですか?

現時点では、TypeStruct1 つのフィールドのみを持つ別の構造体を作成しましたtype。JSON を にデコードし、TypeStruct型の値に基づいて受信メッセージに適切な構造体を選択し、メッセージを再度デコードします。

このデコードの重複を取り除きたいと思います。

4

1 に答える 1

8

既存の列挙型逆シリアル化を使用できます。フォーマットを次の列挙型に逆シリアル化するための段階的な例を示します。

#[derive(Debug, PartialEq, Eq, Deserialize)]
enum MyType {
    A {gar: ()},
    B {test: i32},
    C {blub: String},
}
  1. json 文字列の例から始めます。

    let json = r#"{"type": "B", "test": 42}"#;
    
  2. Value列挙型に変換します

    let mut json: serde_json::Value = serde_json::from_str(json).unwrap();
    
  3. typeフィールドを引き裂く

    let type_ = {
        let obj = json.as_object_mut().expect("object");
        let type_ = obj.remove("type").expect("`type` field");
        if let serde_json::Value::String(s) = type_ {
            s
        } else {
            panic!("type field not a string");
        }
    };
    
  4. 「適切な」列挙型 json を作成します。フィールドの名前が列挙バリアントであり、フィールドの値がバリアント値である単一のフィールドを持つ構造体

    let mut enum_obj = std::collections::BTreeMap::new();
    enum_obj.insert(type_, json);
    let json = serde_json::Value::Object(enum_obj);
    
  5. 生成された json デシリアライザーを使用して、json を列挙型の値に変換します

    let obj: MyType = serde_json::from_value(json).unwrap();
    
于 2015-10-26T13:27:07.087 に答える