Rust serde 对一个混合数组进行反序列化

4
在Rust中,我从一个websocket接收数据。为简单起见,代码如下:

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

我从 websocket 得到的字符串确实是具有双引号的 '浮点数值'(实际上是字符串),以及没有引号的整数。

我希望将该对象反序列化为结构体。但由于返回的数组 "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返回混合类型的数组是否与serde反序列化过程不兼容?

1个回答

2

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,
}

很少需要自己实现Visitor;由serde提供的Deserialize宏非常可定制。但是,如果您想省略额外的结构体,那就必须这样做。
如果一些数字表示为JSON字符串,则可能需要更多工作,但是您仍然可以在没有自定义Visitor实现的情况下完成。请参见:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接