问题
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:
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:
- How to transform fields during deserialization using Serde?
- How to transform fields during serialization using Serde?
- Serde field attributes
来源:https://stackoverflow.com/questions/57903579/rust-serde-deserializing-a-mixed-array