3
votes

In Rust i am receiving data from a websocket. For simplicity it looks like this:

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

The string i get from the websocket is indeed double-quoted 'floating point values' (thus in actuality strings), and unquoted integers.

I want to deserialize this object into a struct. But since the return array "a" is of mixed type, I can't use something like:

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

So I thought let's define another struct:

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

 struct MyStruct {
    id: i32,
    a: Ask
 }

But how should I write the deserializer for this? Looking at the serde docs I understand that I should write a Visitor for Ask:

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

But what would be the Value type then?

So I'm sure I am not correctly understanding how the deserialization process works. Or is the fact that the Websocket returns an array of mixed types just incompatible with the serde deserialization process?

1

1 Answers

2
votes

Serde can deserialize to a Rust struct from sequence-like structures as well as map-like ones.

Your structs are almost right, but there is an extra layer of hierarchy in your JSON. If your JSON was:

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

then this will just work, with the right serde annotations:

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

If you can't change the JSON, you can use an extra layer of structs to match:

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

It is rare that you need to implement your own Visitor; the Deserialize macro provided by serde is quite customisable. However, if you want to omit the extra struct, that's what you'd have to do.

You may need to do more work if some of the numbers are represented as JSON strings, but you can still do that without a custom Visitor implementation. See: