< 返回版块

LongRiver 发表于 2023-07-25 09:07

我想定义一个表示浮点数的struct类型,并且在为其实现serde时,表现的就像是一个浮点数,而不是一个struct。

下面是源码。上半部分是MyFloat的定义和serde实现。下半部分的main函数是用json和msgpack的测试。

这里为了简单起见,MyFloat内部只是一个f64。但在实际代码中,这个类型的定义更加复杂,所以这里不能直接用serde(transparent),而是必须手动实现serde。

use serde::{Serialize, Deserialize, Serializer, Deserializer};

// impl Serialize and Deserialize for MyFloat
#[derive(Debug)]
struct MyFloat {
    inner: f64
}
impl Serialize for MyFloat {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.inner.serialize(serializer)  // <---- dump as float number
    }
}
impl<'de> Deserialize<'de> for MyFloat {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        use serde::de::{self, Visitor};
        struct MyFloatVistor;
        impl<'de> Visitor<'de> for MyFloatVistor {
            type Value = MyFloat;
            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(formatter, "MyFloat")
            }
            fn visit_f64<E>(self, f: f64) -> Result<Self::Value, E>
                where E: de::Error,
            {
                Ok(MyFloat { inner: f })  // <----- parse float number
            }
        }

        deserializer.deserialize_str(MyFloatVistor)
    }
}

// test using struct Req
#[derive(Serialize, Deserialize, Debug)]
struct Req {
    num: MyFloat,
}

fn main() {
    let req = Req {
        num: MyFloat { inner: 123.456 }
    };

    // MsgPacker
    let ser = rmp_serde::to_vec_named(&req).unwrap();
    println!("MsgPacker serialized = {:?}", ser);

    let de: Req = rmp_serde::from_slice(&ser).unwrap();
    println!("MsgPacker deserialized = {:?}", de);  // <==== good

    // json
    let ser = serde_json::to_string(&req).unwrap();
    println!("json serialized = {}", ser);

    let de: Req = serde_json::from_str(&ser).unwrap();
    println!("json deserialized = {:?}", de);  // <==== fail !!!
}

其运行结果如下:

MsgPacker serialized = [129, 163, 110, 117, 109, 203, 64, 94, 221, 47, 26, 159, 190, 119]
MsgPacker deserialized = Req { num: MyFloat { inner: 123.456 } }
json serialized = {"num":123.456}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid type: floating point `123.456`, expected MyFloat", line: 1, column: 14)', src/main.rs:59:46

可以看到msgpack的ser/de都正常。但json的de就失败了。

我以为msgpack和json是类似的格式,都是自描述的。但是为什么我的这个情况中,msgpack可以,但是json就失败呢?

评论区

写评论
araraloren 2023-07-25 10:24

因为你用错函数了.. deserialize_f64

作者 LongRiver 2023-07-25 10:21

确实,是这里写错了。。。。。

改成deserializer.deserialize_f64,就好了。

这里之前是从其他地方copy过来的。漏掉改这里了。

多谢

Pikachu 2023-07-25 09:39
-- deserializer.deserialize_str(MyFloatVistor);
++ deserializer.deserialize_f64(MyFloatVistor);

我不知道你的message pack是怎么解析成功的,但是既然你的visitor只实现了f64的方法,那你也只应该调用deserialize_f64.

1 共 3 条评论, 1 页