`#[serde(default)]` versus `impl Default`

I have a large struct with various configuration values in it, something like:

struct Style {
    foreground: f32,
    background: f32,
    size: [f32; 2],

I have defined the defaults for these using Default, like so:

impl Default for Style {
    fn default() -> Self {
        Self {
            foreground: 0.4,
            background: 0.8,

I now want to load this from a file, allowing any of the fields to by omitted - and if they are omitted it just uses the default value.

So using serde_derive I did this:

#[derive(Deserialize, Serialize)]
struct Style {
    foreground: f32,
    background: ...

However the #[serde(default)] annotation uses the default value of a f32 (which is 0.0), so if I load an empty document I'll get a bunch of 0.0 instead of the values from the impl Default

I'm doing something like this:

let style = if let Some(path) = cli_options.override_settings {
    let s: Style = serde_whatever.load(path).unwrap();
} else {

The problem is how to define the default values once, for both the serde-loading and non-serde code paths?

Things I've thought of are:

  1. #[serde(default="...")] seems to require passing a function, which would then mean one function for each of the many struct entries which is impractical
  2. I could define each of the Style entries as Option<f32> etc. That way the default is None - then I can do let mut style = Style::default(); and merge the loaded settings with style.update(serde_whatever.load(path)); - this would work okay, but requires wrapping everything in Option which is wrong (as the values aren't optional, and would thus require more clutter like style.foreground.unwrap())

I think you'll have to define a function for each unfortunately.

You can apply #[serde(default)] directly on the struct instead of the fields (source).

When deserializing, any missing fields should be filled in from the struct's implementation of Default. Only allowed on structs.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.