Hello, I would like to use serde to deserialize an array of (string or array of string) to an array of string.
Actually it an { items: { kind: "a" | "b", name: string | string } } to { items: { kind: "a" | "b", name: string } }, sorry for the TS notation, the playground should be clearer.
But I can't figure it out
use serde::{Deserialize, Serialize};
fn main() {
first_try();
second_try();
third_try();
}
fn first_try() {
#[derive(Debug, Clone, Deserialize, Serialize)]
struct Data {
items: Vec<Item>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
struct Item {
kind: Kind,
name: String
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum Kind {
A,
B,
}
let data = r#"
{
"items": [
{
"kind":"a",
"name": "a-1"
},
{
"kind":"a",
"name": "a-2"
},
{
"kind":"b",
"name": "b-1"
}
]
}"#;
let items = serde_json::from_str::<Data>(data).expect("Cannot deserialize config");
dbg!(items); // this works
// But I would like to be able to set multiple item of the same kind in one object
// like in `second_try`
}
fn second_try() {
let data = r#"
{
"items": [
{
"kind":"a",
"name": ["a-1", "a-2"]
},
{
"kind":"b",
"name": "b-1"
}
]
}"#;
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
enum OneOrManyString {
One(String),
Many(Vec<String>)
}
#[derive(Debug, Clone, Deserialize, Serialize)]
struct Data {
items: Vec<Item>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
struct Item {
kind: Kind,
name: OneOrManyString
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum Kind {
A,
B,
}
let items = serde_json::from_str::<Data>(data).expect("Cannot deserialize config");
dbg!(items); // this works but is deserialized as
/*
Data {
items: [
Item {
kind: A,
name: Many(
[
"a-1",
"a-2",
],
),
},
Item {
kind: B,
name: One(
"b-1",
),
},
],
}
and I would like the same as in first_try:
Data {
items: [
Item {
kind: A,
name: "a-1",
},
Item {
kind: A,
name: "a-2",
},
Item {
kind: B,
name: "b-1",
},
],
}
*/
}
Here is a playground link: Rust Playground