36594


Rustにおいて、自分の定義した構造体

[code]

    struct MyStruct {
      a: i32,
      b: f64,
    }
    
[/code]

をmsgpackの辞書として保存するにはどうすれば良いでしょうか？

`serde_derive`を用いて以下のようにした場合、Listとして保存されてしまいます：

[code]

    extern crate rmp_serde;
    extern crate serde;
    #[macro_use]
    extern crate serde_derive;
    
    use serde::Serialize;
    
    #[derive(Serialize)]
    struct A {
        a: i32,
        b: f64,
    }
    
    fn main() {
        let f = ::std::fs::File::create("test.msg").ok().unwrap();
        let mut buf = ::std::io::BufWriter::new(f);
        let mut enc = ::rmp_serde::Serializer::new(&mut buf);
        let val = A { a: 12, b: 1.2 };
        val.serialize(&mut enc).unwrap();
    }
    
[/code]

この`test.msg`を[msgpack-cli](https://github.com/jakm/msgpack-cli)で表示すると

[code]

    % msgpack-cli decode test.msg
    [12,1.2]
    
[/code]

のようにリストで保存されていることがわかります。  
これを`{a: 12, b: 1.2}`のような辞書形式で保存するには上記のRustコードをどのように変更すればよいでしょうか？


CC BY-SA 3.0
2017-07-22T12:53:27.073
36588
2017-07-22T14:38:50.597
9572
question
rust msgpack
serde.rsで構造体をmsgpackの辞書としてシリアライズするには？


`rmp_serde::Serializer` は [`Serializer::with`](https://docs.rs/rmp-
serde/0.13.5/rmp_serde/encode/struct.Serializer.html#method.with)
というコンストラクタを用意しており、第2引数に渡す型に応じて構造体のシリアライズ方式を変更できます。

[code]

    use rmp::Marker;
    use rmp::encode::{write_map_len, write_str, ValueWriteError};
    use rmp_serde::encode::VariantWriter;
    use std::io::Write;
    
    pub struct StructMapWriter;
    
    impl VariantWriter for StructMapWriter {
        fn write_struct_len<W>(&self, wr: &mut W, len: u32) -> Result<Marker, ValueWriteError>
        where W: Write
        {
            write_map_len(wr, len)  // write_array_len -> write_map_len
        }
    
        fn write_field_name<W>(&self, wr: &mut W, key: &str) -> Result<(), ValueWriteError>
        where W: Write
        {
            write_str(w, key) // OK(()) -> write_str
        }
    }
    
    fn main() {
        // ... omit
        let mut enc = Serializer::with(&mut buf, StructMapWriter);
        // ...
    }
    
[/code]

※デフォルトで使用される `StructArrayWriter` は[ここ](https://github.com/3Hren/msgpack-
rust/blob/master/rmp-serde/src/encode.rs#L76-L93)で定義されています。


CC BY-SA 3.0
2017-07-22T14:31:01.457
36594
2017-07-22T14:38:50.597
2017-07-22T14:38:50.597
24530
24530
36588
answer


rmp_serdeのドキュメントを読む限り、リストとして保存する仕様なようなのでrmp_serdeを使ってmapとして保存するのは難しいでしょう。  
別のクレートを使うか自分でmapとして保存するシリアライザを書くことになりそうです。  
調べたところ[corepack](https://crates.io/crates/corepack)というライブラリが[structをmapとしてシリアライズ](https://docs.rs/corepack/0.2.1/src/corepack/ser.rs.html#322)しているようだったのでそれを使うか、そのコードを参考に自作することになるかと思います。（コード例を示してませんがこれで回答になるでしょうか。


CC BY-SA 3.0
2017-07-22T14:38:16.263
36595
2017-07-22T14:38:16.263
22816
36588
answer