Is is possible in Symfony Serializer
to deserialize an array of objects in a property? I have a Boss
class with the $Npc = []
property that needs to hold a array of Npc
objects. I did see some examples in the documentation, but they do not state this feature. I have a json string with an array of NPC's For example:
class Boss {
private $Npc = [];
/**
* @return Npc[]
*/
public function getNpcs(): array
{
return $this->npcs;
}
}
I am using php7.1 and symfony/serializer version ^3.3.
Edit: I already tried PhpDocExtractor, but it would not let me install it. :(
Edit: This is a possible JSON value:
{
"bossname": "Epic boss!",
"npcs": [{
"id": 24723,
"name": "Selin Fireheart",
"urlSlug": "selin-fireheart",
"creatureDisplayId": 22642
}]
}
The following (full) example is working for me with Symfony 5.3 components. It combines some of the above and adds some more necessary parts:
The Serializer needs to include ArrayDenormalizer
as well as ObjectNormalizer
. The ObjectNormalizer
needs proper configuration. The full creation can look like this:
return new Serializer(
[
new ArrayDenormalizer(),
new DateTimeNormalizer(),
new ObjectNormalizer(
null,
null,
null,
new ReflectionExtractor()
),
],
[
new JsonEncoder(),
]
);
It seems like order is important regarding the normalizer / denormalizer, probably due to priority. Placing DateTimeNormalizer
after ObjectNormalizer
won't work.
The target class needs to provide three methods in order to allow mapping of an array of other classes:
class Place
{
/**
* @var OpeningHour[]
*/
protected $openingHours = [];
/**
* @return OpeningHour[]
*/
public function getOpeningHoursSpecification(): array
{
return $this->openingHours;
}
public function addOpeningHoursSpecification(OpeningHour $openingHour): void
{
$this->openingHours[] = $openingHour;
}
public function removeOpeningHoursSpecification(OpeningHour $openingHour): void
{
}
}
All three methods need to exist. The first in order to allow Serializer to fetch existing values and allow comparison. The other two need to exist in order to adapt existing value to match expected one by adding missing and removing no longer existing entities.
The above does not provide implementation for removal as this is taken from a one way project.
I found a way to do this :). I installed the Symfony PropertyAccess package through Composer. With this package, you can add adders, removers and hassers. This way Symfony Serializer will automaticly fill the array with the correct objects. Example:
private $npcs = [];
public function addNpc(Npc $npc): void
{
$this->npcs[] = $npc;
}
public function hasNpcs(): bool
{
return count($this->npcs) > 0
}
etc.
This way you can use the ObjectNormalizer with:
$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
Edit: At least since v3.4 you have to create a remover method as well. Otherwise it just won't work (no error or warning).
I have struggled with this many hours without getting a result. Every time i added an adder function, the objectnormalizer wanted to invoke this function but got an error something like "The field xyz should be of type xyz[], array given".
This is cause i forgot to add the ArrayDenormalizer
to the normalizer pool of the serializer. After adding this, everything worked fine.
Hope this is helpful for somebody.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With