serde
serde copied to clipboard
Fallible defaults for non-present fields
I want to be able to get configuration from a file, where individual fields can also be presented as environment variables.
The closest things to what I want are these attribute macros:
-
deserialize_with
: as far as I can tell, this isn't run at all if the field isn't present -
default
: has to be infallible
So either a version of deserialize_with
that is run even if the field isn't present at all (has some logic that can product a value in spite of this), or a version of default
that returns a Result
. If the field isn't present, and the default fails, that error will be propagated up to the deserialization caller.
Currently I'm using a default
that panics if the values aren't found. This is fine for my current use case, but I'd like to be able to more gracefully handle that error.
Hi there,
I've a somewhat similar problem when a field is missing and I want to use deserialize_with
. When using serde_json
, I'm accustomed to the fact that fields of type Option<T>
can be omitted from the json
string if they are null
and deserialization will still work fine. If I provide a deserialize_with
function, this behavior is disabled and parsing fails for fields that are omitted.
Here an example from the playground:
use serde::Deserialize;
#[derive(Deserialize)]
struct Foo {
#[serde(deserialize_with = "deserialize_wrapper")]
bar: Option<bool>,
}
fn deserialize_wrapper<'de, D>(
d: D,
) -> Result<Option<bool>, D::Error>
where
D: serde::de::Deserializer<'de>,
{
Option::deserialize(d)
}
fn main() {
let json = "{}";
let f: Foo = serde_json::from_str(json).unwrap();
assert_eq!(f.bar, None);
}
The wrapper function does nothing really, but parsing the empty json object panics in line 21 with the following error:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("missing field `bar`", line: 1, column: 2)', src/main.rs:21:45
If you comment out the deserialize_with
field attribute in line 5, parsing works as expected.
I believe adding #[serde(default)]
to the optional field will fix the issue. See this related issue: https://github.com/serde-rs/serde/issues/1728#issuecomment-579480080
Yes, adding the #[serde(default)]
tag solves my problem, thanks
I want to be able to get configuration from a file, where individual fields can also be presented as environment variables.
The closest things to what I want are these attribute macros:
1. `deserialize_with`: as far as I can tell, this isn't run at all if the field isn't present 2. `default`: has to be infallible
So either a version of
deserialize_with
that is run even if the field isn't present at all (has some logic that can product a value in spite of this), or a version ofdefault
that returns aResult
. If the field isn't present, and the default fails, that error will be propagated up to the deserialization caller.Currently I'm using a
default
that panics if the values aren't found. This is fine for my current use case, but I'd like to be able to more gracefully handle that error.
I propose #[serde(try_default = function)]
, where function
is a function with no arguments returning Result. All error types that serde::de::Error::custom
accepts should be supported, i.e. everything that implements Display.
I think I would prefer not to build something for try_default
into serde_derive. But if someone wanted to put together a more fully featured derive macro as a separate library, plenty of people would be excited about that.