Use properties' declared defaults when rendering whole-type defaults - #1041
Use properties' declared defaults when rendering whole-type defaults#1041danieleades wants to merge 1 commit into
Conversation
ee1428c to
0bb49b6
Compare
|
Why is this the right handling for this schema? |
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`.
0bb49b6 to
a366dc8
Compare
|
Typify has to choose how to project a declared JSON object default into a Rust value. The consistency rule I am using is that For JSON Schema itself treats |
|
Just so I know: am I talking to a human or an agent? |
A human. Or an agent that's been instructed to say that if anyone asks... Getting hard to tell these days! |
|
Ok, human: are there other reasonable interpretations to consider? Have you looked at what other code generation tools do? My read of the spec is that there's no specific meaning for the property. |
so the OpenAPI/JSON Schema specs seem to be fairly silent on how a code generator should turn
A third option would be to reject a declared default that doesn’t validate against the schema. That would apply if The ecosystem seems kind of split. OpenAPI Generator’s Java output behaves broadly like this PR, although the implementation is different. Other generators, including OpenAPI Generator’s Rust output, tend to fall back to language defaults or ignore schema defaults at runtime. So I don’t think this PR is implementing behaviour required by the spec. It’s making a Typify design choice: I think if the current behaviour is to be maintained that should be recorded as a deliberate choice |
Fixes #662
When typify renders a whole-type default value — a struct type's
defaultused for itsimpl Default, or a parent property's default expression — properties absent from the default JSON object were filled in withDefault::default(), ignoring those properties' own declareddefaultvalues from the schema.Using the schema from #662:
previously generated
which disagrees with what deserializing the declared default value
{}produces (the per-property serde default functions yieldSome("#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:
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 namedDefault.The
types-with-defaults.jsongolden test is extended with theSeparatorConfig/SeparatorHolderexample from the issue, covering both adefault: {}(all properties filled from their declared defaults) and a partialdefault: { "lineThickness": 5 }(the remaining properties filled from their declared defaults).