2

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
pd176
  • 821
  • 3
  • 10
  • 20
  • Data serialization and deserialization is usually best done using [Serde](//serde.rs), which has an implementation for Messagepack. – E_net4 Mar 27 '19 at 11:07

1 Answers1

8

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Stargateur
  • 24,473
  • 8
  • 65
  • 91