Deserialize a entities array with Symfony Serializer Component and AbstractNormalizer::OBJECT_TO_POPULATE

Tags: , , , ,



I already deserialize into a array of object with :

$encoders = [new JsonEncoder()];
$normalizers = [new ObjectNormalizer(), new GetSetMethodNormalizer(), new ArrayDenormalizer()];
$serializer = new Serializer($normalizers, $encoders);

$clients = $serializer->deserialize($myJson, 'AppEntityClient[]', 'json');

And also deserialize one entity into existing one (to no INSERT but UPDATE in db) :

$clientDb = $clientRepository->find(1);
$client = $serializer->deserialize($myJson, Client::class, 'json', [AbstractNormalizer::OBJECT_TO_POPULATE => $clientDb ]);

But when I want to do both, doctrine only insert in DB:

$clients = $serializer->deserialize($myJson, 'AppEntityClient[]', 'json', [AbstractNormalizer::OBJECT_TO_POPULATE => $clientRepository->findAll()]);

Did I miss something ?

— The official doc I found did not mention it: https://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object

EDIT: I manage to do it manually with decode json into array, then loop on it, re-encode into json each item in loop and finally deserialize them. But if there is a way to do it without decode/loop/encode I prefer to use it !

Answer

Check the following information from the documentation you mentioned yourself:

The AbstractNormalizer::OBJECT_TO_POPULATE is only used for the top level object. If that object is the root of a tree structure, all child elements that exist in the normalized data will be re-created with new instances.

When the AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE option is set to true, existing children of the root OBJECT_TO_POPULATE are updated from the normalized data, instead of the denormalizer re-creating them. Note that DEEP_OBJECT_TO_POPULATE only works for single child objects, but not for arrays of objects. Those will still be replaced when present in the normalized data.

So based on that it is not supported to populate an array of objects at once. You’ll have to go through your array.



Source: stackoverflow