我有如下数据类型:
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Matrix {
#[serde(rename = "numColumns")]
pub num_cols: usize,
#[serde(rename = "numRows")]
pub num_rows: usize,
pub data: Vec<f64>,
}
我的JSON正文看起来像这样:
{
"numRows": 2,
"numColumns": 1,
"data": [1.0, "NaN"]
}
这是Jackson(从我们使用的Java服务器)提供的序列化,并且是有效的JSON。不幸的是,如果我们致电serde_json::from_str(&blob)
,则会收到错误消息:
Error("invalid type: string "NaN", expected f64", [snip]
我知道浮点数周围有一些微妙之处,人们对应该采用的方式抱有很大的看法。我尊重。特别是Rust,我非常乐于助人,我喜欢。
但是,到最后,这些JSON Blob才是我要接收的,并且我需要"NaN"
字符串以反序列化为某个f64
值,其中is_nan()
为true ,并将其序列化回字符串"NaN"
,因为该生态系统的其余部分都使用了Jackson,在那很好。
这可以通过合理的方式实现吗?
编辑:建议的链接问题讨论了如何覆盖派生的derializer,但并未解释如何专门对float进行反序列化。
答案 0 :(得分:1)
实际上似乎在Vec(或Map等)中使用自定义解串器是Serde上的一个未解决问题,并且已经使用了一年多(截至撰写本文时):https://github.com/serde-rs/serde/issues/723 < / p>
我相信解决方案是为f64
(这很好)以及使用f64
作为子对象的所有东西(例如Vec<f64>
,{{1 }}等。不幸的是,这些方法的实现看起来像不是
HashMap<K, f64>
拥有反序列化器后,您只能通过访问者与其进行交互。
长话短说,我最终使它工作了,但是似乎很多代码不是必需的。将其张贴在这里,希望(a)某人知道如何清除它,或(b)确实是应该这样做,并且此答案对某人有用。我花了整整一天的时间认真阅读文档并进行反复试验,所以这可能对其他人很有用。 deserialize<'de, D>(deserializer: D) -> Result<Vec<f64>, D::Error>
where D: Deserializer<'de> { /* snip */ }
函数应与字段名称上方的适当(de)serialize_float(s)
一起使用。
#[serde( (de)serialize_with="etc." )]