I'm trying to port a JavaScript library which uses msgpack for encoding JavaScript objects to Rust. I found a Rust library for msgpack encoding/decoding, but I don't get what is the equivalent input format in Rust.
This JavaScript code for encoding the object {"a": 5, "b": 6}
gives the output 82 a1 61 03 a1 62 05:
const msgpack = require("msgpack-lite");
msgpack.encode(obj);
I tried representing the object as a Rust struct and encoding it using rmp-serde library
use rmp_serde::{Deserializer, Serializer};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Test {
a: u32,
b: u32,
}
fn main() {
let mut buf = Vec::new();
let val = Test { a: 3, b: 5 };
val.serialize(&mut Serializer::new(&mut buf)).unwrap();
println!("{:?}", buf);
}
I get the output [146, 3, 5]. How do I represent JSON input in Rust?
What is the Rust equivalent of a JavaScript object
That is a HashMap:
use rmp_serde::{Deserializer, Serializer, encode::StructMapWriter};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)]
pub struct Test {
a: u32,
b: u32,
}
fn main() {
let mut buf = Vec::new();
let mut val = HashMap::new();
val.insert("a", 3);
val.insert("b", 5);
val.serialize(&mut Serializer::new(&mut buf)).unwrap();
println!("{:x?}", buf);
let test: Test = Deserialize::deserialize(&mut Deserializer::new(&buf[..])).unwrap();
println!("{:?}", test);
buf.clear();
test.serialize(&mut Serializer::with(&mut buf, StructMapWriter))
.unwrap();
println!("{:x?}", buf);
}
This gives the expected output:
[82, a1, 61, 3, a1, 62, 5]
Test { a: 3, b: 5 }
[82, a1, 61, 3, a1, 62, 5]
As you can see, you can deserialize into something other than a HashMap but serialization will not produce the same thing because you "lost" the information that it was a HashMap. The default of rmp is to use compact serialization ("This is the default constructor, which returns a serializer that will serialize structs using compact tuple representation, without field names."), but you can tell to rmp to serialize it differently if you need to with StructMapWriter.
There is actually much cleaner and convenient way of achieving the same goal. Suppose you have a struct that has different types for different values:
use rmp_serde::{Deserializer, Serializer};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Test {
a: u32,
b: String,
}
To serialize it like a json object, you'll need to:
fn main() {
let mut buf = Vec::new();
let val = Test { a: 3, b: "hello world".into() };
val.serialize(&mut Serializer::new(&mut buf).with_struct_map()).unwrap();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With