2013-05-13 14 views
11

Próbuję zaktualizować podmioty symfony2/doktryny przy użyciu JMSSerializer z zasadą @ExclusionPolicy: None @Groups Inclusion.jak zaktualizować jednostkę symfony2/doktrynę z zasady włączania @Grouper JMSSerializer z postaci szeregowej

* @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; 
} 

referencyjny: http://jmsyst.com/libs/serializer/master/reference/annotations

wynika z następującego zapisu:

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

są szeregowane za pomocą integracji grupy, aby uniknąć szeregowania informacji nie potrzeba (stowarzyszenia, plamy, itp ..), więc gdy chcę zaktualizować jednostkę, deserializuję tylko zaktualizowane pola jednostki z JSON.

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

result: 
{id:1,flagged:true} 

który po przejściu z powrotem do aplikacji deserializes do podmiotu

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

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

Problem jest, gdy próbuję połączyć jednostkę z powrotem do kierownika jednostki doktryna:

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

The Wynikowy foo próbuje zaktualizować wykluczone właściwości (name, created_by) o wartości null.

Jak mogę powiedzieć, że JMSSerializer lub Doctrine Entity Manager łączą, że nie chcę nadpisywać istniejących właściwości null?

+0

jedyną możliwą opcją znalezioną na http://stackoverflow.com/questions/8726611/how-to-update-a-doctrine-entity-from-a-serialized-json, która oznacza ominięcie JMSSerializer, deserializację i sprawdzenie/aktualizację encja ręcznie (w tym przypadku przykład pomija settery). – Heyflynn

Odpowiedz

17

Znalazłem odpowiedź.

$serializer to usługa stworzona przez pakiet integracji symfony2 JMSSerializerBundle.

Domyślna obsługa jest jms_serializer.serializer inicjuje JMSSerializer z domyślnego obiektu Constructor UnserializeObjectConstructor i dla doktryny musiałem deserializowania z DoctrineObjectConstructor.

bo używam tylko JMSSerializer w projekcie dla serializacji/deserializacji podmiotów doktryny I nadpisałeś JMSSerializerBundle „s jms_serializer.object_constructor z aliasu właściwego serwisu konstruktora obiektu.

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

Czy istnieje lepszy sposób, aby skonfigurować co obiekt konstruktor używa serializer?

Dodałem też właściwego kontekstu deserializowania:

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

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

Korzystanie z konstruktora obiektu doktryna, że ​​domyśla się, że chcę, aby znaleźć obiekt i zastosować tylko aktualizacje polach w $jsonFoo (i flagi Grupa). To całkowicie eliminuje potrzebę łączenia się menedżera encji doktryn i mogę po prostu utrzymywać obiekt poprawnie.

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

oprócz odpowiedzi @ Heyflynna (dzięki!), Musiałem to do pracy z doctrine_mongodb, więc zmodyfikowane mójservices.yml następująco:

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 

ważnym faktem jest @doctrine_mongodb jako argument dla jms_serializer.doctrine_object_constructor zamiast oryginału doctrine parametr w wiązka naservices.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" /> 
1

Aby użyć deserializatora JMS dla dokumentów MongoDB i jednostek ORM, można użyć

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 

Jak widać jms_serializer.doctrine_object_constructor drugiego argumentu (fallbackConstructor) jest jms_serializer.doctrine_mongodb_object_constructor oznacza to, że jeśli obiekt nie jest podmiotem następnie JMS spróbuje użyć fallbackConstructor i jeśli deserialised obiekt nie jest ani Dokument zostanie użyta domyślna unserialize_object_constructor

jeśli deserializowania podmiotowi

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

jeśli dokument

$dm->persist($foo); 
$dm->flush(); 
Powiązane problemy