Skip to content

Use properties' declared defaults when rendering whole-type defaults#1041

Open
danieleades wants to merge 1 commit into
oxidecomputer:mainfrom
danieleades:fix/whole-type-default-props
Open

Use properties' declared defaults when rendering whole-type defaults#1041
danieleades wants to merge 1 commit into
oxidecomputer:mainfrom
danieleades:fix/whole-type-default-props

Conversation

@danieleades

Copy link
Copy Markdown
Contributor

Fixes #662

When typify renders a whole-type default value — a struct type's default used for its impl Default, or a parent property's default expression — properties absent from the default JSON object were filled in with Default::default(), ignoring those properties' own declared default values from the schema.

Using the schema from #662:

"separator": {
  "$ref": "#/definitions/SeparatorConfig",
  "default": {}
}

previously generated

super::SeparatorConfig {
    line_color: Default::default(),      // -> None
    line_thickness: Default::default(),  // -> 0
}

which disagrees with what deserializing the declared default value {} produces (the per-property serde default functions yield Some("#B2000000") / 1). So the rendered default did not mean what the schema says it means.

With this change, a property absent from the whole-type default is rendered from its own declared default when it has one:

super::SeparatorConfig {
    line_color: ::std::option::Option::Some("#B2000000".to_string()),
    line_thickness: 1_i64,
}

falling back to Default::default() only when the property declares no default. While here, the fallback is fully qualified as ::std::default::Default::default(), since a schema can legitimately define a type named Default.

The types-with-defaults.json golden test is extended with the SeparatorConfig/SeparatorHolder example from the issue, covering both a default: {} (all properties filled from their declared defaults) and a partial default: { "lineThickness": 5 } (the remaining properties filled from their declared defaults).

When rendering a whole-type default value (used for a type's impl
Default and for parent properties' serde default functions), properties
absent from the default JSON object were filled in with
`Default::default()`, ignoring the properties' own declared schema
defaults. This made the rendered default disagree with deserialization,
which fills in absent properties via their serde default functions.

For example, given a property with `"default": 42` and a whole-type
default of `{}`, the rendered default produced `0` where deserializing
`{}` produces `42`.

Render absent properties using their declared default value when one
exists, falling back to `Default::default()` otherwise. Also fully
qualify that fallback as `::std::default::Default::default()` so it
cannot collide with a schema-defined type named `Default`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Specifying default value for an object should use object's existing default field values

1 participant