11

我正在尝试使用带有 @ExclusionPolicy:None @Groups 包含策略的 JMSSerializer 更新 symfony2/doctrine 实体。

 * @Serializer\ExclusionPolicy("none")
 */
 class Foo
 {
    /**
     * @Serializer\Groups({"flag","edit"})
     */
    protected $id;

    /**
     * @Serializer\Groups({"edit"})
     */
    protected $name;

    /**
     * @Serializer\Groups({"flag"})
     */
    protected $flag;

    /**
     * @Serializer\Exclude()
     */
    protected $createdBy;
 }

参考:http: //jmsyst.com/libs/serializer/master/reference/annotations

以下记录的结果:

Foo (id:1, name:'bar', flagged:false ,created_by:123)

使用组包含进行序列化以避免序列化我不需要的信息(关联、blob 等)所以当我想更新一个实体时,我只反序列化来自 JSON 的实体的更新字段。

$foo->setFlagged(true);
$data = $serializer->serialize($foo, 'json', SerializationContext::create()->setGroups(array("flag")));

result:
{id:1,flagged:true}

当传递回应用程序时,它会反序列化到实体中

$foo = $serializer->deserialize($jsonFoo,'Foo','json');

result:
Foo (id:1, name:null, flagged:true, created_by:null)

问题是当我尝试将实体合并回理论实体管理器时:

$foo = $em->merge($foo);
$em->persist($foo);
$em->flush();

结果 foo 正在尝试使用 null 更新排除的属性 (name,created_by)。

如何告诉 JMSSerializer 或 Doctrine Entity Managers 合并我不想用 null 覆盖现有属性?

4

3 回答 3

17

I found the answer.

$serializer is a service created by the symfony2 integration bundle JMSSerializerBundle.

The default service is jms_serializer.serializer initializes the JMSSerializer with the default Object Constructor UnserializeObjectConstructor and for doctrine I needed to deserialize with the DoctrineObjectConstructor.

because I only use JMSSerializer in the project for serialize/deserialize of doctrine entities, I overwrote JMSSerializerBundle's jms_serializer.object_constructor with the alias of the proper object constructor service.

<service id="jms_serializer.object_constructor" alias="jms_serializer.doctrine_object_constructor" public="false"/>

Is there a better way to configure what object constructor the serializer uses?

I also added the proper context to deserialize:

$serializer->deserialize($jsonFoo,'Foo','json', DeserializationContext::create()->setGroups(array('flag')));

result:
Foo (id:1, name:'bar', flagged:true ,created_by:123)

Using the doctrine object constructor, it figures out that I want to find the object and only apply updates to fields provided in $jsonFoo (and the flag group). This totally eliminates the need for doctrines entity manager merge and I can just persist the object properly.

$em->persist($foo);
$em->flush();
于 2013-05-13T17:27:26.633 回答
4

除了@Heyflynn 的回答(谢谢!),我还需要它来使用doctrine_mongodb,所以我修改了我 services.yml的如下:

services:
    jms_serializer.doctrine_object_constructor:
        class:        %jms_serializer.doctrine_object_constructor.class%
        public:       false
        arguments:    ["@doctrine_mongodb", "@jms_serializer.unserialize_object_constructor"]

    jms_serializer.object_constructor:
        alias: jms_serializer.doctrine_object_constructor

重要的事实是@doctrine_mongodbas 参数代替了bundle 中的jms_serializer.doctrine_object_constructor原始doctrine参数: services.xml

    <service id="jms_serializer.doctrine_object_constructor" class="%jms_serializer.doctrine_object_constructor.class%" public="false">
        <argument type="service" id="doctrine"/>
        <argument type="service" id="jms_serializer.unserialize_object_constructor"/>
    </service>
    <service id="jms_serializer.unserialize_object_constructor" class="%jms_serializer.unserialize_object_constructor.class%" public="false" />
    <service id="jms_serializer.object_constructor" alias="jms_serializer.unserialize_object_constructor" public="false" />
于 2013-06-26T18:33:57.213 回答
1

要将 JMS 反序列化器用于 MongoDB 文档和 ORM 实体,您可以使用

jms_serializer.doctrine_mongodb_object_constructor:
    class:        %jms_serializer.doctrine_object_constructor.class%
    public:       false
    arguments:    ["@doctrine_mongodb", "@jms_serializer.unserialize_object_constructor"]

jms_serializer.doctrine_object_constructor:
    class:        %jms_serializer.doctrine_object_constructor.class%
    public:       false
    arguments:    ["@doctrine", "@jms_serializer.doctrine_mongodb_object_constructor"]

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

正如您在jms_serializer.doctrine_object_constructor第二个参数(fallbackConstructor)中看到的那样jms_serializer.doctrine_mongodb_object_constructor,这是否意味着如果您的对象不是实体,那么 jms 将尝试使用 fallbackConstructor,并且如果您的反序列化对象也不是 Document,那么将默认使用unserialize_object_constructor

如果你反序列化实体

$em->persist($foo);
$em->flush();

如果文件

$dm->persist($foo);
$dm->flush();
于 2017-07-28T21:07:26.553 回答