Search code examples
rustserdeserde-json

Require a field to be an integer or null, but not missing in JSON


I want to deserialize the following struct using serde_json. The parent_id field should accept an integer or a null, but I want it to return an error if the field is missing.

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
   pub name: String,
   pub parent_id: Option<i32>,
}

// this is accepted
serde_json::from_value(json!({
   "name": "Group 1",
   "parent_id": null,
});

// this should return an error
serde_json::from_value(json!({
   "name": "Group 1",
});

I tried using the code above, but parent_id would be deserialized into a None even though it doesn't exist.


Solution

  • You can deserialize_with with custom function to get the expected behaviour.

    use serde::{Deserialize, Deserializer, Serialize};
    use serde_json::json;
    
    
    #[derive(Debug, Serialize, Deserialize)]
    pub struct Group {
       pub name: String,
       #[serde(deserialize_with = "Option::deserialize")]
       pub parent_id: Option<i32>,
    }
    
    fn main() {
        // thread 'main' panicked at src/main.rs:25:10:
        // called `Result::unwrap()` on an `Err` value: Error("missing field 
        // `parent_id`", line: 0, column: 0)
        let r: Group = serde_json::from_value(json!({
            "name": "Group 1",
         })).unwrap();
        println!("{:?}", r);
    
    }