add #[serde(default)] to Node (and, perhaps other similar structs) (#18883)
# Objective
Many structs that implement `Serialize` and `Deserialize` (when Bevy's
`serialize` feature is enabled) also implement `Default`, but _do not_
apply the `#[serde(default)]` attribute. This requires those who want to
deserialize said structs to explicitly specify **all** struct fields in
their data-interchange format, even if they all end up being their
default values.
For example, I am trying to implement a plugin that allows me to specify
a UI tree in JSON files. I noticed that when I tried to deserialize the
`Node` component (which has **39** fields!) with `serde`, I was met with
an error that in essence would have required me to specify all fields of
`Node` in the JSON file, of which I was only using non-default values
for:
- `height`
- `width`
- `border`
- `flex_direction`
## Solution
1. Apply #[serde(default)] to the `Node` struct
2. If '1' is reasonable, perhaps start a conversation about applying
this attribute to all structs that implement `Serialize`, `Deserialize`,
and `Default` ?
After applying this attribute on a local fork of Bevy, I was able to
deserialize my UI tree exactly as intended with minimal markup in my
JSON files.
There might be a reason not to do this that I am not aware of, I tried
looking for similar past issues but could not find much conversation
about `#[serde(default)]`. Documentation on this attribute can be found
[here](https://serde.rs/container-attrs.html#default).
> #[serde(default = "path")]
>
> When deserializing, any missing fields should be filled in from the
object returned by the given function or method. The function must be
callable as fn() -> T. For example default = "my_default" would invoke
my_default() and default = "SomeTrait::some_default" would invoke
SomeTrait::some_default(). Only allowed on structs.
## Testing
I did not write any formal tests for this. Informally, I simply added
`#[serde(default)]` to `Node` to a local fork of Bevy and successfully
deserialized an instance of `Node` with default values not specified in
my JSON file.
## Sample JSON
Note how I only needed to specify 4/39 fields for `Node`. Upon
deserialization, `serde` invoked `Node::default()` to populate the
missing fields.
```c
{
"UiRoot": {
"Node": {
"height": {"Percent": 100.0},
"width": {"Percent": 100.0},
"border": {"left": {"Px": 5.0}, "right": {"Px": 5.0}, "top": {"Px": 5.0}, "bottom": {"Px": 5.0}},
"flex_direction": "Row"
},
"BorderColor": {"Srgba": {"red": 1.0, "green": 0.0, "blue": 0.0, "alpha": 1.0}},
"Children": ["CreateGameButton"]
},
"CreateGameButton": {
"Node": {
"height": {"Percent": 25.0},
"width": {"Percent": 25.0},
"border": {"left": {"Px": 5.0}, "right": {"Px": 5.0}, "top": {"Px": 5.0}, "bottom": {"Px": 5.0}},
"flex_direction": "Row"
},
"BorderColor": {"Srgba": {"red": 0.0, "green": 1.0, "blue": 0.0, "alpha": 1.0}},
"Interaction": "None"
}
}
```
Co-authored-by: Carter Anderson <mcanders1@gmail.com> T
T.J. Given committed
4e403b615e08843ca546362a9f369e54300979e2
Parent: 055f0f5
Committed by GitHub <noreply@github.com>
on 5/22/2026, 2:27:23 PM