Skip to content

Keep the values of an existing object for missing fields - #232

Open
DavidBadura wants to merge 1 commit into
3.0.xfrom
populate-without-defaults
Open

DavidBadura wants to merge 1 commit into
3.0.xfrom
populate-without-defaults

Conversation

@DavidBadura

Copy link
Copy Markdown
Member

Hydrating an existing object with Hydrator::OBJECT_TO_POPULATE set promoted properties to their default value if their field was missing in the data. Updating only the name of a profile therefore also reset every other promoted property with a default. Defaults are now only used for new objects, missing fields keep the current value of the object.

The ReflectionMapper skips missing fields for existing objects. The generated mappers get a separate populate() path without the defaults, but only for classes with promoted defaults, so the code for new objects and the nested entry points stays the same. The upgrade guide mentions the changed behaviour.

This came up while porting the groups extension (#231): properties outside the selected groups must not be reset either when an object is populated.

@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Hello 👋

Here are the most recent benchmark results, compared against 3.0.x. Time is the mode over the iterations in the its column, with the relative standard deviation in brackets.

GeneratedHydrator

subject revs its memory base current diff
benchHydrate1Object 1000 5 1.855mb -21.23% 0.797μs (±2.44%) 0.790μs (±0.90%) -0.81%
benchExtract1Object 1000 5 1.855mb -21.23% 0.936μs (±1.20%) 0.939μs (±0.55%) +0.26%
benchHydrate1000Objects 3 5 1.855mb 0.00% 767.902μs (±0.64%) 770.604μs (±0.91%) +0.35%
benchExtract1000Objects 3 5 1.855mb 0.00% 483.785μs (±1.79%) 485.659μs (±1.71%) +0.39%

StackHydrator

subject revs its memory base current diff
benchHydrate1Object 1000 5 1.855mb 0.00% 1.540μs (±10.14%) 1.547μs (±1.10%) +0.49%
benchExtract1Object 1000 5 1.855mb 0.00% 1.977μs (±2.14%) 1.918μs (±1.23%) -2.98%
benchHydrate1000Objects 3 5 1.855mb 0.00% 1.483ms (±1.05%) 1.475ms (±0.91%) -0.57%
benchExtract1000Objects 3 5 1.855mb 0.00% 1.454ms (±0.60%) 1.457ms (±0.60%) +0.20%

StackHydratorWithLazy

subject revs its memory base current diff
benchHydrate1Object 1000 5 1.855mb 0.00% 0.343μs (±2.65%) 0.341μs (±2.78%) -0.59%
benchHydrate1ObjectTriggerInit 1000 5 1.855mb 0.00% 2.174μs (±1.65%) 2.130μs (±0.43%) -2.00%
benchHydrate1000Objects 3 5 1.855mb 0.00% 329.208μs (±2.01%) 332.374μs (±1.70%) +0.96%
benchHydrate1000ObjectsTriggerInit 3 5 1.855mb 0.00% 2.117ms (±1.42%) 2.122ms (±0.95%) +0.19%

StackHydratorWithCryptography

subject revs its memory base current diff
benchHydrate1Object 1000 5 1.855mb 0.00% 2.616μs (±0.49%) 2.605μs (±6.04%) -0.41%
benchExtract1Object 1000 5 1.855mb 0.00% 7.841μs (±1.62%) 7.940μs (±2.09%) +1.26%
benchHydrate1000Objects 3 5 1.855mb 0.00% 2.562ms (±4.00%) 2.575ms (±0.38%) +0.51%
benchExtract1000Objects 3 5 1.855mb 0.00% 7.299ms (±1.71%) 7.260ms (±1.16%) -0.53%

GeneratedHydratorWithCryptography

subject revs its memory base current diff
benchHydrate1Object 1000 5 1.855mb 0.00% 1.881μs (±0.48%) 1.849μs (±0.73%) -1.69%
benchExtract1Object 1000 5 1.855mb 0.00% 6.552μs (±1.76%) 6.525μs (±1.13%) -0.42%
benchHydrate1000Objects 3 5 1.855mb 0.00% 1.817ms (±3.77%) 1.819ms (±1.04%) +0.06%
benchExtract1000Objects 3 5 1.855mb 0.00% 6.086ms (±1.66%) 6.041ms (±1.06%) -0.73%

This comment gets updated every time a new commit comes in.

Hydrating with OBJECT_TO_POPULATE set promoted properties to their default
value if their field was missing, so an update overwrote values which were not
part of the data. Defaults are now only used for new objects.

The generated mappers get an own populate path for classes with promoted
defaults, so the code for new objects stays the same.
@DavidBadura
DavidBadura force-pushed the populate-without-defaults branch from 625c869 to ee9bd6c Compare October 19, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant