3

私の実際の型はより大きく、より複雑ですが、私はこのような型を持っています:

struct MyType {
    i: u32,
}

この型を実装Deserializeすると、serde は次のようなものを探します (JSON に興味があります)。

{"i":100}  

バイト配列からも逆シリアル化できるようにカスタマイズしたいと思います。

[1, 2, 3, 4]

配列を処理する impl を作成できますが、serde で残りを自動生成する必要があります (これは になりますvisit_map)。

impl<'de> Deserialize<'de> for MyType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct MyTypeVisitor;

        impl<'de> Visitor<'de> for MyTypeVisitor {
            type Value = MyType;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "struct or array of 4 integers")
            }

            fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
                // ...
            }
        }

        // deserializer.deserialize_any(MyTypeVisitor)
    }
}

それは可能ですか?この例では難しくありませんが、構造体が大きい場合、手書きのデシリアライズは面倒です。

これは、Serde を使用して逆シリアル化中にフィールドを変換する方法の複製ではありませんか? deserialize_with1つのフィールドでのみ機能するためです。私の本当のタイプでそれをどのように機能させるか理解できません:

pub enum Component {
    String(StringComponent),
    Translation(TranslationComponent),
    Score(ScoreComponent),
    Selector(SelectorComponent),
}

pub struct StringComponent {
    #[serde(flatten)] pub base: Base,
    pub text: String,
}

pub struct Base {
    // ...
    extra: Option<Vec<Component>>,
    // ...
}

私がやりたいことは次のとおりです。

  • 逆シリアル化中に、入力が数値の場合は を返しますComponent::Stringvisit_iこれは/ u/f64と友達と一緒に行うことができます。
  • 入力が文字列の場合は、Component::String再び a を返します。visit_strこれは/で実行できますstring
  • input が array の場合[..]、通常どおりデシリアライズしますが、array[1..] の要素を array[0] の extra に割り当てます。これは によって行うことができますvisit_seq
  • 入力がマップの場合は、serde 派生に処理させます。
4

1 に答える 1