Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deserialize in Rust (using serde) optional json parameter that can be either string or string array

Tags:

rust

serde

I am new to Rust and I am trying to deserialize JSON data using serde library. I have following JSON structure:

{
    “foo”: “bar”,
    “speech”: “something”
}

or

{
    “foo”: “bar”,
    “speech”: [“something”, “something else”]
}

or

{
    “foo”: “bar”,
}

I.e. speech is optional and it can be either string or array of strings.

I can handle deserializing string/array of string using following approach:

#[derive(Debug, Serialize, Deserialize)]
   struct foo {
   pub foo: String,
   #[serde(deserialize_with = "deserialize_message_speech")]
   speech: Vec<String>
}

I can also handle deserializing optional string/string array attribute using approach:

#[derive(Debug, Serialize, Deserialize)]
struct foo {
   pub foo: String,
   #[serde(skip_serializing_if = "Option::is_none")]
   speech: Option<Vec<String>>
}

or

struct foo {
   pub foo: String,
   #[serde(skip_serializing_if = "Option::is_none")]
   speech: Option<String>
}

But combining it all together simply does not work. It seems deserialize_with does not work properly with Option type. Can somebody advice most straightforward and trivial way how to implement this (serde can be pretty complex, I have seen some crazy stuff :) )?

like image 434
Adam Bezecny Avatar asked Jul 13 '26 00:07

Adam Bezecny


1 Answers

Try using an Enum type for the speech field:

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Speech {
    Str(String),
    StrArray(Vec<String>),   
}

#[derive(Debug, Serialize, Deserialize)]
   struct foo {
   pub foo: String,
   speech: Option<Speech>,
}

Enum is the go-to way to represent a variant type in Rust. See https://serde.rs/enum-representations.html for more detail.

like image 103
Pandemonium Avatar answered Jul 14 '26 20:07

Pandemonium



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!