Before :
foreach ($nestedAttributes as $property => $serializedPath) {
if (null === $value = $propertyAccessor->getValue($normalizedData, $serializedPath)) {
...
After :
foreach ($nestedAttributes as $property => $serializedPath) {
if ($serializedPath->getElement(0) === '@parentKey') {
if (!isset($context['deserialization_path'])) {
throw new \Error('Deserialized objet have no parent');
}
preg_match("/\[(?'key'\w*)\]$/", $context['deserialization_path'], $matches);
if (!isset($matches['key'])) {
throw new \Error('Deserialized objet is not emmbed in array');
}
$value = $matches['key'];
} elseif (null === $value = $propertyAccessor->getValue($normalizedData, $serializedPath)) {
...
class ItemDTO
{
#[SerializedPath('[@parentKey]')]
public ?string $slug = null;
public ?string $name = null;
public ?string $description = null;
}
How it works ?
It's a little hack that use the SerializedPath attribute to communicate with the ObjectNormaliser with a custom special path '@parentKey'.
The new object normalizer detect this path and look in the deserialization context to find the key value.
How to improve ?
The best symfony way would be a new tag to do the job. But it needs to create multiple new files like AttributeMetadata, AttributeLoader down to ObjectNormalizer and inject them into right services.