Why are new entities instantiated with null for all values except the data in the json, why is the entity constructor not setting defaults - putting a die() in the constructor never gets executed.
Ok so digging into the code, when no managed entity is found, JMSS will use the doctrine instantiator class to create the entity - its sole job, to create entities without calling the constructor. Is there a reason for this? this is inside JMS\Serializer\Construction\UnserializeObjectConstructor
I've configured the object constructor to use the doctrine object constructor written by JMS, but the same issue happens with and without this.
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
Existing entities are updated without trouble, however new entities are missing all constructor set defaults.
Under 'fields' element 0 is existing, element 1 is new.
array (size=3)
'id' => int 2
'name' => string 'Categories' (length=10)
'fields' =>
array (size=2)
0 =>
array (size=7)
'id' => int 49
'displayName' => string 'Car Branded' (length=11)
'type' => string 'checkboxlist' (length=12)
'required' => boolean false
'disabled' => boolean false
'name' => string 'h49' (length=3)
1 =>
array (size=3)
'type' => string 'email' (length=5)
'name' => string 'field3491' (length=9)
'displayName' => string 'Email' (length=5)
The entity looks like this after deserializing:
object(stdClass)[2000]
public '__CLASS__' => string 'AppBundle\Entity\FormElement' (length=28)
public 'id' => null
public 'label' => string 'Email' (length=5)
public 'type' => string 'email' (length=5)
public 'defaultValue' => null
public 'required' => null
public 'mappedField' => null
public 'garbageCollection' => null
public 'sortOrder' => null
public 'disabled' => null
public 'uuid' => null
public 'form' => null
public 'multiOptions' => null
public 'filters' => null
public 'submissions' => null
The entity constructor:
public function __construct()
{
$this->required = false;
$this->disabled = false;
$this->garbageCollection = false;
$this->sortOrder = 0;
$this->type = 'text';
}
And finally this is how im deserializing:
$serializer = $this->get('jms_serializer');
$entryForm = $serializer->deserialize($json_data, 'AppBundle\Entity\EntryForm', 'json');
The issue is the default ObjectConstructor uses Doctrine's Instantiator, which does not call the class' constructor. To solve this, you can create your own ObjectConstructor that just returns a new instance of the class.
Example:
<?php
namespace AppBundle\Serializer;
use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\VisitorInterface;
class ObjectConstructor implements ObjectConstructorInterface
{
/**
* {@inheritdoc}
*/
public function construct(
VisitorInterface $visitor,
ClassMetadata $metadata,
$data,
array $type,
DeserializationContext $context
) {
$className = $metadata->name;
return new $className();
}
}
If you're using the bundle, just set jms_serializer.unserialize_object_constructor.class
parameter to that new class. Otherwise in your builder, use the class as your object constructor.
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