【问题标题】:JMS serializer - Why are new objects not being instantiated through constructorJMS 序列化程序 - 为什么不通过构造函数实例化新对象
【发布时间】:2015-08-11 17:21:24
【问题描述】:

为什么除了 json 中的数据之外的所有值都用 null 实例化新实体,为什么实体构造函数没有设置默认值 - 在构造函数中放置 die() 永远不会被执行。

更新:

好吧,深入研究代码,当没有找到托管实体时,JMSS 将使用学说实例化器类来创建实体——它的唯一工作是在不调用构造函数的情况下创建实体。是否有一个原因?这是在JMS\Serializer\Construction\UnserializeObjectConstructor

里面

我已将对象构造函数配置为使用 JMS 编写的学说对象构造函数,但无论有没有这个,都会出现同样的问题。

jms_serializer.object_constructor:
    alias: jms_serializer.doctrine_object_constructor
    public: false

现有实体可以顺利更新,但新实体缺少所有构造函数集默认值。

在“字段”下,元素 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');

【问题讨论】:

    标签: php symfony doctrine-orm jmsserializerbundle


    【解决方案1】:

    问题是默认的 ObjectConstructor 使用 Doctrine 的 Instantiator,它不调用类的构造函数。为了解决这个问题,您可以创建自己的 ObjectConstructor,它只返回类的新实例。

    例子:

    <?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 参数设置为该新类。否则,在您的构建器中,使用该类作为您的对象构造器。

    【讨论】:

    • 您能解释一下如何将jms_serializer.unserialize_object_constructor.class 设置为新类吗?
    • 他的意思是将jms_serializer.unserialize_object_constructor.class配置选项设置为你自己实现ObjectConstructorInterface的路径,在本例中为AppBundle\Serializer\ObjectConstructor
    • 对于序列化程序包 ^3.0 覆盖类 parameter 不再适用于我。有效的是覆盖jms_serializer.unserialize_object_constructor 服务 将其指向class: AppBundle\Serializer\ObjectConstructor
    • 更新给遇到这个问题的人:这就够了jms_serializer.unserialize_object_constructor: class: AppBundle\Serializer\UnserializeObjectConstructor 不需要添加别名:jms_serializer.object_constructor: alias: jms_serializer.doctrine_object_constructor public: false 否则你会遇到循环引用
    【解决方案2】:

    对我有用的只是将它添加到 jms_serializer 配置中:

    jms_serializer:
        object_constructors:
            doctrine:
                fallback_strategy: "fallback"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多