'Deserializer never called when field is not present
I have a custom serializer and deserializer. where the a field
is of type Option<i32>
and turns into stringified "i32"
when serializing or skips the field if it is None
.
The problem is when I try to deserialize back to struct which has no a field
present.
The print statements are never called either
Error:
thread 'main' panicked at 'called
Result::unwrap()
on anErr
value: Error("missing fielda
", line: 1, column: 13)', src/main.rs:32:45
use std::error::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::str::FromStr;
#[derive(Serialize, Deserialize, Debug)]
struct MyBox {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(serialize_with = "ser_a", deserialize_with = "de_a")]
a: Option<i32>,
b: String,
}
fn main() -> Result<(), Box<dyn Error>> {
let e = MyBox {
a: None,
b: "oklol".to_string(),
};
let f: String = serde_json::to_string(&e).unwrap();
let g: MyBox = serde_json::from_str(&f).unwrap(); // Error occurs here
Ok(())
}
fn ser_a<S>(a: &Option<i32>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let a = a.unwrap().to_string();
s.serialize_str(&a)
}
fn de_a<'de, D>(d: D) -> Result<Option<i32>, D::Error>
where
D: Deserializer<'de>,
{
println!("{:#?}", ("hello!"));
let opt: Option<String> = Option::deserialize(d)?;
match opt {
Some(s) => {
let g = i32::from_str(&s);
match g {
Ok(x) => {
println!("hello1 {:#?}", (x));
Ok(Some(x))
}
Err(x) => {
println!("hello2 {:#?}", (x));
Ok(None)
}
}
}
None => {
println!("hello3 {:#?}", ());
Ok(None)
}
}
}
Solution 1:[1]
There are two things at play here.
- When using custom deserializers,
Option
s are no longer treated as optional when deserializing. - Custom deserializers (provided via
deserialize_with
) will only be called if the field is present in the structure to be deserialized.
If you want a default value for a field that is not present, you'll have to use either #[serde(default)]
or #[serde(default = "path")]
(docs here).
Note that user @jonasbb already provided this answer in the comments, but I think it would be worthwhile to have it as an answer.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | fresskoma |