Serde json value omit properties on None
Asked Answered
H

1

8

Given the following JsonValue:

let mut schema = json!({
    "level": "strict",
    "rule": {}
});

Where we would dynamically insert values to this JsonValue

let value: json!({
    "type": property.r#type,
    "minLength": property.min_length,
    "maxLength": property.max_length,
    "enum": property.r#enum
});

schema["rule"]
    .as_object_mut()
    .unwrap()
    .insert(
        String::from(property.name), 
        value
    );

// Struct for Property
#[derive(Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SchemaDocumentProperty
{
    pub name: String,
    pub r#type: Option<String>,
    pub min_length: Option<u32>,
    pub max_length: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#enum: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub items: Option<SchemaDocumentPropertyArray>
}

The current output is the following where minLength, maxLength and enum are None:

{
    "type": "string",
    "minLength": null,
    "maxLength": null,
    "enum": null
}

My desired output:

{
    "type": "string"
}

I want to omit all of the None values from the JsonValue macro.

Hallerson answered 2/1, 2022 at 17:59 Comment(0)
B
7

Just create a Value struct instead of using the json! macro:

#[derive(Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Value
{
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub min_length: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_length: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub r#enum: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub items: Option<SchemaDocumentPropertyArray>
}

If you need a serde_json::Value use the to_value method:

let value = Value { ... };
let json_value = serde_json::to_value(value).expect("Valid json value");
Breeder answered 2/1, 2022 at 18:12 Comment(3)
I thought of doing it this way, however the .as_object_mut().unwrap().insert(k, v) only accepts JsonValue on v. The following is thrown: mismatched types expected enum serde_json::Value, found struct SchemaDocumentPropertyrustc (E0308)Hallerson
@Hallerson check the update on how to transform a serializable type to a ValueBreeder
you may want to use serde_with crate's #[skip_serializing_none] once for the whole struct, instead of adding multiple skip_serializing_if. See docs.rs/serde_with/3.4.0/serde_with/…Warmup

© 2022 - 2024 — McMap. All rights reserved.