jms_serializer deserialize serialization symfony jmsserializerbundle

serialization - deserialize - Agregue campos adicionales usando el paquete JMS Serializer



symfony serializer (5)

¿Qué pasa con esto: http://jmsyst.com/libs/serializer/master/handlers

En resumen, define una clase que recibe un objeto y devuelve texto o una matriz (que se convertirá en json).

Usted tiene la clase "IndexedStuff" que contiene un campo calculado extraño que por algún motivo debería calcularse en el momento de la serialización.

<?php namespace Project/Model; class IndexedStuff { public $name; public $value; public $rawData; }

Ahora crea el controlador

<?php namespace Project/Serializer; use JMS/Serializer/Handler/SubscribingHandlerInterface; use JMS/Serializer/GraphNavigator; use JMS/Serializer/JsonSerializationVisitor; use JMS/Serializer/Context; class MyHandler implements SubscribingHandlerInterface { public function setEntityManager(Registry $registry) { // Inject registry instead of entity manager to avoid circular dependency $this->em = $registry->getEntityManager(); } public static function getSubscribingMethods() { return array( array( ''direction'' => GraphNavigator::DIRECTION_SERIALIZATION, ''format'' => ''json'', ''type'' => ''Project/Model/IndexedStuff'', ''method'' => ''serializeIndexedStuffToJson'', ), ); } public function serializeIndexedStuffToJson(JsonSerializationVisitor $visitor, Project/Model/IndexedStuff $stuff, array $type, Context $context) { // Build your object here and return it $score = $this->em->find("ProjectBundle:Calculator", $stuff->value) return array("score" => $score->getIndexScore(), "name"=> $score->name } }

Finalmente registrar el servicio

services: project.serializer.stuff: class: Project/Serializer/MyHandler calls: - [setEntityManager, ["@doctrine"]]

Ahora donde quieras serializar un objeto de tipo "IndexedStuff" obtendrás un JSON como este

{"name": "myName", "score" => 0.3432}

De esta manera, puede personalizar completamente cómo se serializa su entidad

Tengo una entidad que normalmente serializo usando el paquete JMS Serializer. Tengo que agregar a la serialización algunos campos que no residen en la propia entidad, pero que se recopilan con algunas consultas db.

Mi idea era crear un objeto personalizado, completar los campos con los campos de entidad y agregar el personalizado. Pero esto parece un poco complicado y costoso de hacer para cada variación (yo uso muchos grupos de serialización) de la clase.

¿Hay una forma mejor / estándar para hacer esto? Usando una fábrica? ¿Eventos de serialización pre / post?

Tal vez puedo escuchar la serialización y verificar el tipo de entidad y los grupos de serialización agregan los campos personalizados. Pero en lugar de hacer una consulta para cada entidad, sería mejor recopilar todos los datos de las entidades relacionadas y luego agregarlas. Cualquier ayuda es apreciada


He encontrado la solución yo solo,

para agregar un campo personalizado después de que se haya realizado la serialización, debemos crear una clase de escucha como esta:

<?php namespace Acme/DemoBundle/Listener; use JMS/DiExtraBundle/Annotation/Service; use JMS/DiExtraBundle/Annotation/Tag; use JMS/DiExtraBundle/Annotation/Inject; use JMS/DiExtraBundle/Annotation/InjectParams; use Symfony/Component/HttpKernel/Event/PostResponseEvent; use Acme/DemoBundle/Entity/Team; use JMS/Serializer/Handler/SubscribingHandlerInterface; use JMS/Serializer/EventDispatcher/EventSubscriberInterface; use JMS/Serializer/EventDispatcher/PreSerializeEvent; use JMS/Serializer/EventDispatcher/ObjectEvent; use JMS/Serializer/GraphNavigator; use JMS/Serializer/JsonSerializationVisitor; /** * Add data after serialization * * @Service("acme.listener.serializationlistener") * @Tag("jms_serializer.event_subscriber") */ class SerializationListener implements EventSubscriberInterface { /** * @inheritdoc */ static public function getSubscribedEvents() { return array( array(''event'' => ''serializer.post_serialize'', ''class'' => ''Acme/DemoBundle/Entity/Team'', ''method'' => ''onPostSerialize''), ); } public function onPostSerialize(ObjectEvent $event) { $event->getVisitor()->addData(''someKey'',''someValue''); } }

De esta forma, puede agregar datos al elemento serializado.

En su lugar, si desea editar un objeto justo antes de la serialización, utilice el evento pre_serialize, tenga en cuenta que ya debe tener una variable (y los grupos de serialización correctos) si desea usar pre_serialize para agregar un valor.


La respuesta aceptada solo funciona cuando el visitante se deriva de /JMS/Serializer/GenericSerializationVisitor . Esto significa que funcionará para JSON, pero no para XML.

Aquí hay un método de ejemplo que hará frente a XML. Mira las interfaces que el objeto visitante admite y actúa de manera adecuada. Muestra cómo puede agregar un elemento de enlace a los objetos serializados JSON y XML ...

public function onPostSerialize(ObjectEvent $event) { //obtain some data we want to add $link=array( ''rel''=>''self'', ''href''=>''http://example.org/thing/1'', ''type''=>''application/thing+xml'' ); //see what our visitor supports... $visitor= $event->getVisitor(); if ($visitor instanceof /JMS/Serializer/XmlSerializationVisitor) { //do XML things $doc=$visitor->getDocument(); $element = $doc->createElement(''link''); foreach($link as $name => $value) { $element->setAttribute($name, $value); } $doc->documentElement->appendChild($element); } elseif ($visitor instanceof /JMS/Serializer/GenericSerializationVisitor) { $visitor->addData(''link'', $link); } }


Me sorprende que nadie haya sugerido una forma mucho más sencilla. Solo necesita usar @VirtualProperty:

<?php // ... /** * @JMS/VirtualProperty * @JMS/SerializedName("someField") */ public function getSomeField() { return $this->getTitle() . $this->getPromo(); }


Para responder más a la pregunta original. Aquí se explica cómo limita los datos agregados para algunos grupos serializados (en este ejemplo, some_data solo se agregan cuando no estamos usando el grupo de la list :

public function onPostSerializeSomeEntityJson(ObjectEvent $event) { $entity = $event->getObject(); if (!in_array(''list'', (array)$event->getContext()->attributes->get(''groups''))) { $event->getVisitor()->addData(''user_access'', array( ''some_data'' => ''some_value'' )); } }

(array)$event->getContext()->attributes->get(''groups'') contiene una matriz de los grupos serializados utilizados.