example-format/src/de.rs at master · serde-rs/example-format
github.com
GitHub - nazo6/serde-deserializer-example
github.com
serde-rs/example-format
のソースコードのリンクを貼っておくのでserdeのドキュメントと見比べていただくとより理解しやすいのではないかと思います。deserialize_*
メソッドを実装するにあたり、あると便利なメソッドがあるので実装しておきます。next_char
と進めずに文字を得るpeek_char
メソッドが実装されています。Deserializer
を実装する上で頭に入れておくと良いことは、Deserializer内部の状態をどんどん変化させながらパースを進めていくということです。deserialize_any
についてfalse
かtrue
の文字列のみをDeserializeできるDeserializeを作成しましたが、その際、deserialize_any
メソッドを実装することでbool
型以外をエラーにしました。しかし、deserialize_any
はそれ以外に重要な用途があり、「Self-describingなデータ」をデシリアライズする際に、デシリアイズするべき構造体の情報を見ずにデシリアライズを行うことができます。{
」はマップ構造、「"
」は文字列を意味する、などです。serde_json
ではserde_json::Value
型を使うことで型を決めなくても柔軟にjsonを処理できますが、これにもdeserialize_any
が活用されているようです。deserialize_any
メソッドは実装されているもの他のdeserialize_*
メソッドも全て実装されており、forward_to_deserialize_any!
が使われていないため実行されることはありません。ですが、せっかくなので今回はdeserialize_*
メソッドは必要な場所のみに実装して可能な限りdeserialize_any
を使うようにしたいと思います。deserialize_any
の実装JsonDeserializer
にdeserialize_any
を実装しました。bool
と()
型はデシリアライザを書いておきました。'de
を付けるだけです。SeqAccess
traitを実装した構造体をvisitor.visit_seq
に与えることでデシリアライズを行います。このトレイトで実装しなければならないのはnext_element_seed
メソッドのみです。CommaSeparated
という構造体に実装されています。CommaSeparated
にはDeserializer
への参照が保持されており、そのライフタイムは'de: 'a
、つまり'de
より短い間有効です。これは直感的に納得できるのではないかと思います。next_element_seed
は配列の各要素をデシリアライズするために呼ばれます。seed: DeserializeSeed
という値が渡されるため、このseed.deserialize
に文字列を与えることでデシリアライズされた要素の中身を得ることができます。next_key_seed → next_value_seed
の順に呼ばれます。CommaSeparated
という概念として構造体を抽象化したのでそれを再利用しています。賢いDeserializer
を書く上で主となる要素はある程度カバーできたのではないかと思います。何か参考になれば幸いです。