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.