2013-05-13 10 views
11

Ich versuche Symfony2/Doktrin-Entitäten mit JMSSerializer mit einer @ExclusionPolicy: None @Groups Inclusion Policy zu aktualisieren.wie man symfony2/doctrine entity von einer @Groups-Einschluss-Richtlinie aktualisiert JMSSerializer deserialized entity

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

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

das Ergebnis für den folgenden Datensatz:

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

serialisiert wird mit Aufnahme-Gruppe Serialisierung Informationen zu vermeiden, brauche ich nicht (Verbände, Blobs, etc ..) Wenn ich eine Entity aktualisieren möchte, deserialiere ich nur die aktualisierten Felder der Entity aus dem JSON.

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

result: 
{id:1,flagged:true} 

die, wenn sie an die Anwendung übergeben zurück deserialisiert in die Einheit

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

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

Das Problem ist, wenn ich versuche, die Einheit wieder in die Lehre Entity Manager zu fusionieren:

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

Die resulting foo versucht, die ausgeschlossenen Eigenschaften (name, created_by) mit null zu aktualisieren.

Wie teile ich JMSSerializer oder Doctrine Entity Managers merge mit, dass ich vorhandene Eigenschaften nicht mit null überschreiben möchte?

+0

die einzige Option, die ich fo http://stackoverflow.com/questions/8726611/how-to-update-a-doctrine-entity-from-a-serialized-json gefunden habe, was bedeutet, JMSSerializers zu umgehen und zu deserialisieren und zu überprüfen/zu aktualisieren die Entität manuell (in diesem Fall die Setter umgehen). – Heyflynn

Antwort

17

Ich fand die Antwort.

$serializer ist ein Dienst, der vom Symfony2-Integrationspaket JMSSerializerBundle erstellt wurde.

Der Standard-Service ist jms_serializer.serializer die JMSSerializer mit dem Standard-Objekt-Konstruktor initialisiert UnserializeObjectConstructor und für Lehre musste ich mit dem DoctrineObjectConstructor deserialisieren.

weil ich serialize/deserialize der Lehre Einheiten für nur JMSSerializer im Projekt verwenden, überschrieb ich JMSSerializerBundle ‚s jms_serializer.object_constructor mit dem Alias ​​des richtigen Objektkonstruktor Service.

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

Gibt es eine bessere Art und Weise zu konfigurieren, welche Objektkonstruktor der Serializer verwendet?

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

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

Mit der Lehre Objektkonstruktor, es herausfindet, dass ich das Objekt und nur anwenden Updates auf Felder in $jsonFoo (und der Flagge versehen finden will:

ich auch den richtigen Kontext deserialisieren hinzugefügt Gruppe). Dadurch wird die Zusammenführung von Dokumentintitätsmanagern vollständig überflüssig und ich kann das Objekt nur korrekt beibehalten.

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

zusätzlich zu @ Heyflynns Antwort (danke!), Musste ich dies mit doctrine_mongodb arbeiten, so modifizierte ich meineservices.yml wie folgt:

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 

wichtige Tatsache, die @doctrine_mongodb als Argument für jms_serializer.doctrine_object_constructor anstelle der ursprünglichen doctrine Parameter in der des Bundle ist 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" /> 
1

Um JMS Deserializer für MongoDB Dokumente und ORM Einheiten verwenden Sie

verwenden können
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 

Wie Sie sehen in jms_serializer.doctrine_object_constructor Sekunden Argument (fallbackConstructor) ist jms_serializer.doctrine_mongodb_object_constructor es bedeutet, dass, wenn Ihr Objekt nicht Entität ist, dann wird jms versuchen fallbackConstructor zu verwenden und wenn Ihr deserialised Objekt nicht entweder Dokument wird dann standardmäßig verwendet werden unserialize_object_constructor

wenn Sie deserialisieren Einheit

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

wenn Dokument

$dm->persist($foo); 
$dm->flush(); 
Verwandte Themen