default does not treat a field being set to null equal to the field being emitted. More concretely, the following code will panic in the line where it attempts to deserialize request_c:
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Request {
#[serde(default = "Priority::lowest")]
priority: Priority,
}
#[derive(Serialize, Deserialize, Debug)]
enum Priority { ExtraHigh, High, Normal, Low, ExtraLow }
impl Priority {
fn lowest() -> Self { Priority::ExtraLow }
}
fn main() {
let request_a: Request = serde_json::from_str(r"{}").unwrap();
println!("{:?}", request_a);
let request_b: Request = serde_json::from_str(r#"{"priority": "High"}"#).unwrap();
println!("{:?}", request_b);
let request_c: Request = serde_json::from_str(r#"{"priority": null}"#).unwrap();
//^~ PANIC: ErrorImpl { code: ExpectedSomeValue, line: 1, column: 14 }
println!("{:?}", request_c);
}
The data I want to process sometimes has its field set, sometimes it is set to null, and sometimes it is omitted. I want to set a default for when it is null or omitted.
This doesn't need to be the default behaviour but having sth like #[serde(default_on_null)] would be really nice :). Thanks to @oli-obk suggesting that on IRC.
I am open to supporting this better. For now the current workaround would be a deserialize_with function that handles null.
use serde::{Deserialize, Deserializer};
#[derive(Serialize, Deserialize, Debug)]
struct Request {
#[serde(default = "Priority::lowest", deserialize_with = "nullable_priority")]
priority: Priority,
}
fn nullable_priority<'de, D>(deserializer: D) -> Result<Priority, D::Error>
where D: Deserializer<'de>
{
let opt = Option::deserialize(deserializer)?;
Ok(opt.unwrap_or_else(Priority::lowest))
}
@dtolnay oh thanks. That's nice and small compared to the monster that I wrote :)...
A default_on_null function would be a reasonable addition to a Serde helper library such as serde-aux or serde_with. I am closing this issue because I don't think we need to introduce a new Serde attribute for this use case.
Hi! Thank you for an awesome serde :)
Sorry for writing to an old thread, just wanted to know why there's a need for a separate attribute? Couldn't default do the trick?
If I understand correctly, in the case of JSON deserializing #[serde(default)] struct from "{}" yields default value, while deserializing from "null" gives error:
invalid type: null, expected struct
Here's an example code
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9cda0c82d5f144615db93666bee84d24
Is that an expected behaviour, or an inconsistency of serde/serde_json? I would expect {} and null both yield a default value.
Thanks in advance!