milosgajdos
milosgajdos

Reputation: 961

Serializing default Enum variant into json with serde_json renders null

I'm trying to serialize a struct which has some Optional enum fields to their default enum variants.

By default I mean the variant marked with the #[default] serde attribute. However, this keeps on deserialising to null instead of the default value.

Here's a simple example

use serde::{Deserialize, Serialize};
use serde_json;

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct Foo {
    pub text: String,
    #[serde(default)]
    pub version: Option<Version>,
}

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub enum Version {
    #[serde(rename = "PlayV1.0")]
    PlayV1,
    #[serde(rename = "PlayV2.0")]
    #[default]
    PlayV2,
}

fn main() {
    let req = Foo {
        text: "Hello, world!".to_string(),
        ..Default::default()
    };

    let json = serde_json::to_string(&req).unwrap();
    println!("{}", json);
}

I have tried omitting the derive(Default) from the enum and instead, implementing my own e.g.

impl Default for Version {
    fn default() -> Self {
        Version::PlayV2
    }
}

However I still get the following json

{"text":"Hello, world!","version":null}

What I'd like is this:

{"text":"Hello, world!","version": "PlayV2.0"}

I'm sure I'm missing something here or maybe this simply isn't even possible.

Upvotes: 0

Views: 668

Answers (2)

cafce25
cafce25

Reputation: 27567

Moved here from the question:

So here's something that works as per Masklinn suggestion

use serde::{Deserialize, Serialize};
use serde_json;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Foo {
    pub text: String,
    #[serde(default)]
    pub version: Option<Version>,
}

impl Default for Foo {
    fn default() -> Self {
        return Foo {
            text: "".to_owned(),
            version: Some(Version::default()),
        };
    }
}

#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub enum Version {
    #[serde(rename = "PlayV1.0")]
    PlayV1,
    #[serde(rename = "PlayV2.0")]
    #[default]
    PlayV2,
}

fn main() {
    let req = Foo {
        text: "Hello, world!".to_string(),
        ..Default::default()
    };

    let json = serde_json::to_string(&req).unwrap();
    println!("{}", json);
}

Upvotes: 0

Masklinn
Masklinn

Reputation: 42592

I have tried omitting the derive(Default) from the enum and instead, implementing my own e.g.

That's the wrong default: Foo::default() will invoke Option::default() which is None. So if you want to override the default value for the version field you need to either remove the Option so that the derived Foo::default calls Version::default, or impl Default for Foo by hand.

Upvotes: 2

Related Questions