3Hren / msgpack-rust

MessagePack implementation for Rust / msgpack.org[Rust]
MIT License
1.17k stars 130 forks source link

Can't handle #[serde(tag = "someKey")] for structure while Deserialization #318

Open harshkumar314e opened 2 years ago

harshkumar314e commented 2 years ago
use rmp_serde::Serializer;
use serde::Serialize;

extern crate rmp_serde;
extern crate serde;
#[macro_use]
extern crate serde_derive;

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
struct  A {
    b: B,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "kind", content = "data")]
#[serde(rename_all = "snake_case")]
pub enum B {
    First(i32),
    Second(Messagedata)
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "someKey")]
pub struct Messagedata {
    status: String,
    message: String,
}

fn main() {
    let a = A {
        b: B::Second (Messagedata { status: "Failure".to_string(), message: "You are not getting the things".to_string() }),
    };
    //SERDE
    let string_data = serde_json::to_string(&a).unwrap();
    println!("data: {:?}", string_data);
    let data = serde_json::from_str::<A>(&string_data).unwrap();
    println!("A: {:?}", data);
    println!("-------------------------------------------------------------------------------");

    //MESSAGEPACK
    let mut buf = Vec::new();
    a.serialize(&mut Serializer::new(&mut buf)).unwrap();
    // println!("a: {:?}", buf);
    let a = rmp_serde::from_slice::<A>(&buf).unwrap();
    println!("a: {:?}", a);
}

Here is error I am getting:

data: "{\"b\":{\"kind\":\"second\",\"data\":{\"someKey\":\"Messagedata\",\"status\":\"Failure\",\"message\":\"You are not getting the things\"}}}"
A: A { b: Second(Messagedata { status: "Failure", message: "You are not getting the things" }) }
-------------------------------------------------------------------------------
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: LengthMismatch(2)', src/main.rs:45:46
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

There is no problem with serializing and deserializing with serde. With rmp_serde there is no problem in serializing a struct with a given tag but while deserializing it is not able to take tag provided as key and giving length error.

kornelski commented 2 years ago

Default encoding doesn't keep field names, so it's unable to know which field was the tag field. If you use .with_struct_map() option it works.

e-ivkov commented 1 year ago

Here is a more minimalist reproduction of this issue - https://github.com/e-ivkov/rmp-bug-repro

I understand that this is not directly a bug, but I would call it an interface inconsistency. It is natural to expect, that if something serialized successfully, it will also de-serialize back. All other serde libraries behave like that.

I would suggest to always use named serialization in rmp_serde, otherwise it simply does not map to serde interface.

kornelski commented 1 year ago

It looks like there are hard trade offs here, as some people want the efficient representation.

https://github.com/3Hren/msgpack-rust/issues/319

shimaowo commented 1 year ago

Just seconding the view that the interface inconsistency is actually broken. Anything that can be serialized should successfully deserialize, and vice-versa. I'm all for stripping names unless opted-in, but that doesn't justify self-inconsistent code.

Does this need a from_slice_named() so that it has to be explicit on both sides? The current behavior is just straight broken.

kornelski commented 1 year ago

Serde doesn't tell the serialiser about existence of any extra options, so at serialisation time there's no way to know if the name is going to be necessary to deserialise or not.

So unfortunately it's up to the user to choose named serialisation if they rely on it.