Deserializing a JSON array containing different types to a struct

To deserialize a JSON array that contains different types, I implemented a custom deserializer and a visitor to create a struct from the array. The array has always the same length and the same types.

Example: [2342394, "234.3", "243.2", 949] should be deserialized to

CustomStruct {
  a: u32,
  b: String,
  c: String,
  d: u32,
}

It seems my custom deserializer is confusing Serde, which somehow expects an array even in other places, when it's not necessary. A minimal example showing the problem is here:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7cbc01a3ace6cf5feffbeba984d90a74

In your sample JSON the last key is nested underneath result, thus it is part of the HashMap and the integer value cannot be deserialized as a Vec<Candle>. You need to move a closing bracket } in front of last.

Is there a reason why you are not using this definition of Candle?

#[derive(Debug, Default, Deserialize)]
#[serde(expecting = "expecting [<timestamp>, <open>, <high>, <low>, <close>, <vwap>, <volume>, <trades>] array")]
pub struct Candle {
    pub timestamp: u32,
    pub open: String,
    pub high: String,
    pub low: String,
    pub close: String,
    pub vwap: String,
    pub volume: String,
    pub trades: u32,
}
2 Likes

Is there a reason you actually need the visitor ? serde seems to handle this case fine. Playground.

Your playground edited.

2 Likes

@jonasbb @erelde Thank you both. The whole issue was caused by me not seeing that "last" was nested. Indeed, this simple definition now works well:

#[derive(Debug, Deserialize)]
pub struct OHLCResult {
    pub error: Vec<String>,
    pub result: CandleData,
}

#[derive(Debug, Deserialize)]
pub struct CandleData {
    #[serde(flatten)]
    pub data: HashMap<String, Vec<Candle>>,
    pub last: u32,
}

Thanks to #[serde(flatten)], all the keys that are different from "last" end up in the HashMap, and the struct is deserialized automatically from the array as you both mentioned.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.