Deserialize JSON array and replace null elements with zeros

I'm using serde to deserialize array of numbers containing null elements.
For example: [1.1, 2.2, 3, null, null, 4.5, 5]

During the deserialization, I need to replace nulls with 0, so the deserialized array would be a Vec { 1.1, 2.2, 3.0, 0.0, 0.0, 4.5, 5.0}

I've tried to write custom deserializer using Deserialize, Deserializer, Visitor and SeqAccess but no luck so far :frowning:

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);
}
1 Like