How to serialize a nested `struct` with custom field names using Serde and CSV

#1

I am implementing a plotting library (which I plan to publish on crates.io) based on the following data model:

#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub struct DataVar<'a, T>
where
    T: Serialize,
{
    pub name: &'a str,
    pub val: &'a [T],
    pub fmt: &'a str,
}

impl<'a, T> DataVar<'a, T>
where
    T: Serialize,
{
    pub fn new(name: &'a str, val: &'a [T], fmt: &'a str) -> Self {
        Self { name, val, fmt }
    }
}

#[derive(Debug, PartialEq, Clone, Default)]
pub struct DataSet<'a, T>
where
    T: Serialize,
{
    pub name: &'a str,
    pub datavars: Vec<DataVar<'a, T>>,
}

impl<'a, T> DataSet<'a, T>
where
    T: Serialize,
{
    pub fn new(name: &'a str, datavars: Vec<DataVar<'a, T>>) -> Self {
        Self { name, datavars }
    }
}

Users create DataVars and DataSets as follows:

let x1 = DataVar::new("Var1", &[1.123, 2.123, 3.123], "f2");
let x2 = DataVar::new("Var2", &[4.123, 5.123, 6.123], "f1");
let s = DataSet::new("Set", vec![x1, x2]);

(for now let’s consider floats only).

I’m struggling to understand how to implement (or derive) the serialize methods to achieve the following.

When calling:

let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.serialize(x1)?;
wtr.flush()?;
1.12
2.12
3.12

When calling:

let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.serialize(x2)?;
wtr.flush()?;
4.1
5.1
6.1

When calling:

let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.serialize(s)?;
wtr.flush()?;
Var1,Var2
1.12,4.1
2.12,5.1
3.12,6.1

I also would need to save data to JSON files, but I guess that once I manage to get one format (CSV) it is simple to extend also to the other formats supported by Serde.

Thanks

#2

I would start with JSON and then move on to csv. It would help if you could write what you want your serialization in JSON to look like.

#3

Considering JSON I would need to achieve the following.

When calling:

println!("{}", serde_json::to_string(&x1)?);
[
    1.12,
    2.12,
    3.12
]

When calling:

println!("{}", serde_json::to_string(&x2)?);
[
    4.1,
    5.1,
    6.1
]

When calling:

println!("{}", serde_json::to_string(&s)?);
{
    "Var1": [
        1.12,
        2.12,
        3.12
    ],
    "Var2": [
        4.1,
        5.1,
        6.1
    ]
}

Please notice that while thinking about this JSON example, I slightly modified also the previous CSV example.

Thanks