Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding to Map instead of Object for data serialized using rmp_serde rust messagepack crate #120

Open
twitu opened this issue Oct 16, 2023 · 2 comments

Comments

@twitu
Copy link

twitu commented Oct 16, 2023

I'm sending data from a rust server to a js client. The rust side is using rmp_serde a messagepack crate. And on the JS side is msgpackr. Sending across an object like this gives.

#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    best_friend: Option<Box<Person>>,
    age: usize,
    address: Vec<String>,
}

    // Convert bob to bytes and send it
    let data_bob = to_vec_named(&bob).expect("Serialization failed");
          let message = codec.decode(msg.data)
Received: object
Received Object: Map(4) {
  'name' => 'Bob',
  'best_friend' => Map(4) {
    'name' => 'Alice',
    'best_friend' => Map(4) {
      'name' => 'David',
      'best_friend' => null,
      'age' => 27,
      'address' => [Array]
    },
    'age' => 29,
    'address' => [ '567 Birch St' ]
  },
  'age' => 28,
  'address' => [ '456 Oak St' ]
}

This map has to explicitly be converted into a JS object. Ideally the output should be as below. When doing both encoding and decoding using msgpackr outputs a JS object, as is expected.

Received: object
Received Object: {
  name: 'Bob',
  best_friend: {
    name: 'Alice',
    best_friend: { name: 'David', best_friend: null, age: 27, address: [Array] },
    age: 29,
    address: [ '567 Birch St' ]
  },
  age: 28,
  address: [ '456 Oak St' ]
}

Is there some data/configuration missing on either side for messagepack style ser/de? Am I missing something here?

@kriszyp
Copy link
Owner

kriszyp commented Oct 16, 2023

The default unpack/decode method should be deserializing as objects, but if you created a Unpackr/Packr instance, you can set useRecords: false or mapsAsObjects: true:

const packr = new Packr({ useRecords: false });
unpackr.decode(data);

@twitu
Copy link
Author

twitu commented Oct 16, 2023

Thanks for sharing these options both of them work. useRecords: false and mapsAsObjects: true.

I was trying to do something similar by explicitly creating objects like this below. Do these options do something more efficient? I'm asking because this step will be part in the hot path of the api logic and the most CPU efficient solution will be preferable.

function convertToJsObject(obj) {
  if (obj instanceof Map) {
    const jsObject = {}
    obj.forEach((value, key) => {
      jsObject[key] = convertToJsObject(value)
    })
    return jsObject
  } else if (Array.isArray(obj)) {
    return obj.map((item) => convertToJsObject(item))
  }
  return obj
}

It's also a bit weird that packing and unpacking with msgpackr decodes it to objects just fine. But packing with rmp_serde makes it behave differently.

kravetsone added a commit to kravetsone/elysia-msgpack that referenced this issue Jun 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants