Here is a working quick & dirty solution. playground
Important is the #[serde(transparent) to make it work with your example.
The rest is just a sequence visitor for T: Deserialize<'de> + Default and using seq.next_element::<Option<T>>().
use std::fmt;
use std::marker::PhantomData;
use serde::Deserializer;
use serde::Deserialize;
#[derive(Deserialize, Debug)]
#[serde(transparent)]
struct Outer {
#[serde(deserialize_with = "deserialize_vec")]
data: Vec<f64>,
}
fn deserialize_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de> + Default,
{
use serde::de::{SeqAccess, Visitor};
struct SeqVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for SeqVisitor<T>
where
T: Deserialize<'de> + Default,
{
type Value = Vec<T>;
fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt.write_str("default vec")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut vec = Vec::new();
while let Ok(Some(elem)) = seq.next_element::<Option<T>>() {
vec.push(elem.unwrap_or_default());
}
Ok(vec)
}
}
deserializer.deserialize_seq(SeqVisitor(PhantomData))
}
fn main() {
let ret = serde_json::from_str::<Outer>("[1.1, 2.2, 3, null, null, 4.5, 5]").unwrap();
dbg!(ret);
}