JMS 序列化器 - 为什么新对象没有通过构造函数实例化
JMS serializer - Why are new objects not being instantiated through constructor
为什么除了 json 中的数据以外的所有值都使用 null 实例化新实体,为什么实体构造函数不设置默认值 - 在构造函数中放置 die() 永远不会执行。
更新:
好的,深入研究代码,当没有找到托管实体时,JMSS 将使用学说实例化器 class 来创建实体——它唯一的工作是创建实体而不调用构造函数。是否有一个原因?这是在 JMS\Serializer\Construction\UnserializeObjectConstructor
里面
我已经将对象构造函数配置为使用 JMS 编写的学说对象构造函数,但是使用和不使用它都会发生同样的问题。
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
现有实体更新没有问题,但是新实体缺少所有构造函数集默认值。
在 'fields' 下,元素 0 已存在,元素 1 是新的。
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)
反序列化后的实体如下所示:
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
实体构造函数:
public function __construct()
{
$this->required = false;
$this->disabled = false;
$this->garbageCollection = false;
$this->sortOrder = 0;
$this->type = 'text';
}
最后这就是我反序列化的方式:
$serializer = $this->get('jms_serializer');
$entryForm = $serializer->deserialize($json_data, 'AppBundle\Entity\EntryForm', 'json');
问题是默认的 ObjectConstructor 使用 Doctrine 的 Instantiator,它不调用 class' 构造函数。要解决这个问题,您可以创建自己的 ObjectConstructor,它只是 returns class.
的一个新实例
示例:
<?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();
}
}
如果您使用的是捆绑包,只需将 jms_serializer.unserialize_object_constructor.class
参数设置为新的 class。否则在您的构建器中,使用 class 作为您的对象构造函数。
对我有用的是简单地将其添加到 jms_serializer 配置中:
jms_serializer:
object_constructors:
doctrine:
fallback_strategy: "fallback"
为什么除了 json 中的数据以外的所有值都使用 null 实例化新实体,为什么实体构造函数不设置默认值 - 在构造函数中放置 die() 永远不会执行。
更新:
好的,深入研究代码,当没有找到托管实体时,JMSS 将使用学说实例化器 class 来创建实体——它唯一的工作是创建实体而不调用构造函数。是否有一个原因?这是在 JMS\Serializer\Construction\UnserializeObjectConstructor
我已经将对象构造函数配置为使用 JMS 编写的学说对象构造函数,但是使用和不使用它都会发生同样的问题。
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
现有实体更新没有问题,但是新实体缺少所有构造函数集默认值。
在 'fields' 下,元素 0 已存在,元素 1 是新的。
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)
反序列化后的实体如下所示:
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
实体构造函数:
public function __construct()
{
$this->required = false;
$this->disabled = false;
$this->garbageCollection = false;
$this->sortOrder = 0;
$this->type = 'text';
}
最后这就是我反序列化的方式:
$serializer = $this->get('jms_serializer');
$entryForm = $serializer->deserialize($json_data, 'AppBundle\Entity\EntryForm', 'json');
问题是默认的 ObjectConstructor 使用 Doctrine 的 Instantiator,它不调用 class' 构造函数。要解决这个问题,您可以创建自己的 ObjectConstructor,它只是 returns class.
的一个新实例示例:
<?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();
}
}
如果您使用的是捆绑包,只需将 jms_serializer.unserialize_object_constructor.class
参数设置为新的 class。否则在您的构建器中,使用 class 作为您的对象构造函数。
对我有用的是简单地将其添加到 jms_serializer 配置中:
jms_serializer:
object_constructors:
doctrine:
fallback_strategy: "fallback"