【问题标题】:Rust serde deserializing a mixed arrayRust serde 反序列化混合数组
【发布时间】:2020-01-14 03:31:01
【问题描述】:

在 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 反序列化过程不兼容?

【问题讨论】:

    标签: rust serde


    【解决方案1】:

    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 实现的情况下这样做。见:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多