Rust serde 反序列化混合数组

Rust serde deserializing a mixed array

在 Rust 中,我从 websocket 接收数据。为简单起见,它看起来像这样:

 [1, {"a": ["1.2345", 5, "9.8765"]}]

我从 websocket 获得的字符串确实是双引号 'floating point values'(因此实际上是字符串)和未引号的整数。

我想将这个对象反序列化为一个结构。但是由于 return 数组 "a" 是混合类型,我不能使用类似的东西:

 struct MyStruct {
    id: i32, 
    a: [f64; 3],
 }

所以我想让我们定义另一个结构:

 struct Ask {
    price: f64,
    whole_lot_volume: i64,
    lot_volume: f64
 }

 struct MyStruct {
    id: i32,
    a: Ask
 }

但是我应该如何为此编写反序列化器呢?查看 serde 文档,我明白我应该为 Ask:

写一个 Visitor
 impl<'de> Visitor<'de> for Ask {
    type Value = ...
 }

但是 Value 类型是什么?

所以我确定我没有正确理解反序列化过程的工作原理。还是 Websocket return 是一个混合类型数组与 serde 反序列化过程不兼容?

Serde 可以从类序列结构和类映射结构反序列化为 Rust 结构。

您的结构几乎是正确的,但是您的 JSON 中多了一层层次结构。如果您的 JSON 是:

{
    "id": 1,
    "a": [1.2345, 5, 9.8765]
}

然后这将正常工作,带有正确的 serde 注释:

use serde::{Serialize, Deserialize};

#[derive(Deserialize)]
struct Ask {
    price: f64,
    whole_lot_volume: i64,
    lot_volume: f64,
}

#[derive(Deserialize)]
struct MyStruct {
    id: i32,
    a: Ask,
}

如果无法更改JSON,可以使用额外的结构层来匹配:

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
struct Order {
    price: f64,
    whole_lot_volume: i64,
    lot_volume: f64,
}

#[derive(Debug, Deserialize)]
struct Ask {
    a: Order,
}

#[derive(Debug, Deserialize)]
struct MyStruct {
    id: i32,
    a: Ask,
}

您很少需要实现自己的 Visitorserde 提供的 Deserialize 宏非常可定制。但是,如果您想省略额外的结构,那就是您必须做的。

如果某些数字表示为 JSON 字符串,您可能需要做更多的工作,但您仍然可以在没有自定义 Visitor 实现的情况下完成。参见: