Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Serialización en Symfony con JMSSerializerBundle y el componente Serializer

Serialización en Symfony con JMSSerializerBundle y el componente Serializer

Tener un buen dominio de la serialización es algo fundamental para construir APIs limpias.

Tanto el componente Serializer de Symfony como el JMSSerializerBundle son dos herramientas muy potentes que nos facilitan la tarea de crear diferentes representaciones de nuestros modelos y crear o actualizar esos objetos a partir de sus representaciones.

En esta charla explicaremos cómo funcionan y cómo se utilizan tanto el componente como el bundle, veremos casos de uso interesantes y analizaremos qué fortalezas tiene cada uno de ellos y en qué ocasiones o para qué tareas concretas puede resultar más cómodo uno u otro. Todo ello enfocado desde un punto de vista práctico, con ejemplos que ayuden a ilustrar los distintos usos y situaciones.

Victoria Quirante

July 01, 2017
Tweet

More Decks by Victoria Quirante

Other Decks in Programming

Transcript

  1. Trabajo en Limenius Ofrecemos formación, consultoría y desarrollo a empresas

    Trabajamos con Symfony y React No hay proyecto que no tenga una API El serializador es uno de tus mejores amigos al implementar una API Victoria Quirante @vicqr [email protected]
  2. @vicqr Serialización Es el proceso de codificación de un objeto

    en otro formato que puede ser almacenado, transmitido y posteriormente descodificado
  3. @vicqr Serialización Es el proceso de codificación de un objeto

    en otro formato que puede ser almacenado, transmitido y posteriormente descodificado OBJETOS REPRESENTACIONES (JSON, XML..)
  4. @vicqr Serialización Es el proceso de codificación de un objeto

    en otro formato que puede ser almacenado, transmitido y posteriormente descodificado OBJETOS REPRESENTACIONES (JSON, XML..) Serialización
  5. @vicqr Serialización Es el proceso de codificación de un objeto

    en otro formato que puede ser almacenado, transmitido y posteriormente descodificado OBJETOS REPRESENTACIONES (JSON, XML..) Serialización Deserialización
  6. @vicqr Ejemplo de serialización $responseData = [ 'id' => $spaceship->getId(),

    'name' => $spaceship->getName(), 'color' => $spaceship->getColor(), 'maxSpeed' => $spaceship->getMaxSpeed(), ]; $response = new JsonResponse($responseData, 201); Nuestro objeto -> La response (serialización manual)
  7. @vicqr Ejemplo de serialización $responseData = [ 'id' => $spaceship->getId(),

    'name' => $spaceship->getName(), 'color' => $spaceship->getColor(), 'maxSpeed' => $spaceship->getMaxSpeed(), ]; $response = new JsonResponse($responseData, 201); ... ... $spaceship = new Spaceship(); $spaceship->setName($content['name']); $spaceship->setColor($content['color']); $spaceship->setMaxSpeed($content['maxSpeed']); Nuestro objeto -> La response (serialización manual) La request -> Nuestro objeto (deserialización manual)
  8. @vicqr Ejemplo de serialización $responseData = [ 'id' => $spaceship->getId(),

    'name' => $spaceship->getName(), 'color' => $spaceship->getColor(), 'maxSpeed' => $spaceship->getMaxSpeed(), ]; $response = new JsonResponse($responseData, 201); ... ... $spaceship = new Spaceship(); $spaceship->setName($content['name']); $spaceship->setColor($content['color']); $spaceship->setMaxSpeed($content['maxSpeed']); Apasionante :_( Nuestro objeto -> La response (serialización manual) La request -> Nuestro objeto (deserialización manual)
  9. @vicqr Serialización con serializador $responseData = [ 'id' => $spaceship->getId(),

    'name' => $spaceship->getName(), 'color' => $spaceship->getColor(), 'maxSpeed' => $spaceship->getMaxSpeed(), ]; $response = new JsonResponse($responseData, 201); Convirtiendo nuestro objeto en una Response en JSON
  10. @vicqr Serialización con serializador $responseData = [ 'id' => $spaceship->getId(),

    'name' => $spaceship->getName(), 'color' => $spaceship->getColor(), 'maxSpeed' => $spaceship->getMaxSpeed(), ]; $response = new JsonResponse($responseData, 201); -------------- $response = new Response($serializer->serialize($spaceship, 'json'), 201); Convirtiendo nuestro objeto en una Response en JSON
  11. @vicqr Deserialización con serializador $spaceship = new Spaceship(); $spaceship->setName($content['name']); $spaceship->setColor($content['color']);

    $spaceship->setMaxSpeed($content['maxSpeed']); Convirtiendo el contenido de la Request (JSON) en un objeto
  12. @vicqr Deserialización con serializador $spaceship = new Spaceship(); $spaceship->setName($content['name']); $spaceship->setColor($content['color']);

    $spaceship->setMaxSpeed($content['maxSpeed']); ------------------ $spaceship = $serializer->deserialize($content, Spaceship::class, 'json'); Convirtiendo el contenido de la Request (JSON) en un objeto
  13. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } }
  14. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission”
  15. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo
  16. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo No quiero mostrarlo en el list
  17. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo No quiero mostrarlo en el list Quiero añadir “thumb_”
  18. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo No quiero mostrarlo en el list Quiero añadir “thumb_” Solo en la versión 2 de la API
  19. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo No quiero mostrarlo en el list Quiero añadir “thumb_” Solo en la versión 2 de la API Quiero que sea un campo más
  20. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo No quiero mostrarlo en el list Quiero añadir “thumb_” Solo en la versión 2 de la API Quiero que sea un campo más Con este tipo de cosas es con lo que va a ayudarnos un serializador
  21. @vicqr Datos básicos JMSSERIALIZERBUNDLE - Es un bundle (y librería,

    claro) - Creado por @schmittjoh - Se comenzó en abril de 2011 - Pasó época de poco mantenimiento - Desde hace un año mejor (@goetas_asmir) - Licencia Apache SYMFONY SERIALIZER
  22. @vicqr Datos básicos JMSSERIALIZERBUNDLE SYMFONY SERIALIZER - Es un bundle

    (y librería, claro) - Creado por @schmittjoh - Se comenzó en abril de 2011 - Pasó época de poco mantenimiento - Desde hace un año mejor (@goetas_asmir) - Licencia Apache - Es un Symfony Component - Desarrollado por los core - Se comenzó en enero de 2011 - Se le criticaba que “le faltan muchas cosas” - En continua evolución y mejora - Licencia MIT
  23. @vicqr Inciso: componentes y bundles - Componente -> librería desacoplada

    y reutilizable - Bundle -> atado al Symfony Framework
  24. @vicqr Inciso: componentes y bundles - Componente -> librería desacoplada

    y reutilizable - Bundle -> atado al Symfony Framework A menudo tenemos: Funcionalidad Librería Integración con SF Configuración Inyección de dependencias Bundle +
  25. @vicqr Inciso: componentes y bundles - Componente -> librería desacoplada

    y reutilizable - Bundle -> atado al Symfony Framework A menudo tenemos: Por ejemplo, en el caso del JMSSerializerBundle Funcionalidad Librería Integración con SF Configuración Inyección de dependencias Bundle +
  26. @vicqr JMSSerialiazerBundle - Características - Muchas anotaciones útiles que cubren

    casos de uso muy frecuentes - Muy sencillo empezar a utilizarlo
  27. @vicqr JMSSerialiazer - Instalación y setup - Instalación: - composer

    require - Registrar el bundle http://jmsyst.com/bundles/JMSSerializerBundle
  28. @vicqr JMSSerialiazer - Instalación y setup - Instalación: - composer

    require - Registrar el bundle - Setup: no hay que hacer nada para empezar a usarlo http://jmsyst.com/bundles/JMSSerializerBundle
  29. @vicqr Componente Serializer - Características - No aspira a resolver

    casos de uso concretos sino a proporcionar una arquitectura que te permita hacerlo - Menos “ya hecho”, más flexible Aproximación diferente
  30. @vicqr SF Serializer - Instalación y setup - Instalación: -

    composer require - Si quieres usar ObjectNormalizer instalas también PropertyAccess
  31. @vicqr SF Serializer - Instalación y setup - Instalación: -

    composer require - Si quieres usar ObjectNormalizer instalas también PropertyAccess - Setup: hay que hacer algunas cosas
  32. @vicqr Componente Serializer - Setup use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Encoder\XmlEncoder; use

    Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; $encoders = array(new XmlEncoder(), new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); serializer = new Serializer($normalizers, $encoders);
  33. @vicqr Componente Serializer - Setup use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Encoder\XmlEncoder; use

    Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; $encoders = array(new XmlEncoder(), new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); serializer = new Serializer($normalizers, $encoders); El ObjectNormalizer es muy potente, pero no idóneo para todos los casos
  34. @vicqr JMSSerialiazerBundle - Deserialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships") *

    @Method("POST") */ public function newAction(Request $request) { $serializer = $this->container->get('jms_serializer'); $spaceship = $serializer->deserialize($request->getContent(), Spaceship::class, 'json'); $em = $this->getDoctrine()->getManager(); $em->persist($spaceship); $em->flush(); return new Response("Spaceship created!"); }
  35. @vicqr JMSSerialiazerBundle - Deserialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships") *

    @Method("POST") */ public function newAction(Request $request) { $serializer = $this->container->get('jms_serializer'); $spaceship = $serializer->deserialize($request->getContent(), Spaceship::class, 'json'); $em = $this->getDoctrine()->getManager(); $em->persist($spaceship); $em->flush(); return new Response("Spaceship created!"); }
  36. @vicqr JMSSerialiazerBundle - Serialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships/{name}") *

    @Method("GET") */ public function showAction($name) { $spaceship = $this->getDoctrine() ->getRepository('AppBundle:Spaceship') ->findOneByName($name); $serializer = $this->container->get('jms_serializer'); return new Response($serializer->serialize($spaceship, 'json'), 200); }
  37. @vicqr JMSSerialiazerBundle - Serialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships/{name}") *

    @Method("GET") */ public function showAction($name) { $spaceship = $this->getDoctrine() ->getRepository('AppBundle:Spaceship') ->findOneByName($name); $serializer = $this->container->get('jms_serializer'); return new Response($serializer->serialize($spaceship, 'json'), 200); }
  38. @vicqr JMSSerialiazerBundle - Serialización HTTP/1.1 200 OK Host: localhost:8000 Connection:

    close X-Powered-By: PHP/7.1.0-0ubuntu0.16.04.4 Cache-Control: no-cache, private Date: Sat, 24 Jun 2017 17:45:32 GMT Content-Type: application/json X-Debug-Token: 127f2b X-Debug-Token-Link: http://localhost:8000/_profiler/127f2b {"id":1,"name":"Orion","color":"Razzmic Berry","maxSpeed":8900}
  39. @vicqr Componente Serializer - Deserialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships")

    * @Method("POST") */ public function newAction(Request $request) { $encoders = array(new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); $serializer = new Serializer($normalizers, $encoders); $spaceship = $serializer->deserialize($request->getContent(), Spaceship::class, 'json'); $em = $this->getDoctrine()->getManager(); $em->persist($spaceship); $em->flush(); return new Response("Spaceship created!"); }
  40. @vicqr Componente Serializer - Deserialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships")

    * @Method("POST") */ public function newAction(Request $request) { $encoders = array(new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); $serializer = new Serializer($normalizers, $encoders); $spaceship = $serializer->deserialize($request->getContent(), Spaceship::class, 'json'); $em = $this->getDoctrine()->getManager(); $em->persist($spaceship); $em->flush(); return new Response("Spaceship created!"); }
  41. @vicqr Componente Serializer - Serialización # AppBundle/Controller/Api/SpaceshipController.php /** * @Route("/api/spaceships/{name}")

    * @Method("GET") */ public function showAction($name) { $encoders = array(new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); $serializer = new Serializer($normalizers, $encoders); $spaceship = $this->getDoctrine() ->getRepository('AppBundle:Spaceship') ->findOneByName($name); return new Response($serializer->serialize($spaceship, 'json'), 200); }
  42. @vicqr Comparación inicial Algo de instalación -mínimo- el bundle Algo

    más de configuración el componente En general, para este tipo de ejemplo, idéntico uso
  43. @vicqr Comparación inicial Algo de instalación -mínimo- el bundle Algo

    más de configuración el componente En general, para este tipo de ejemplo, idéntico uso Pero este tipo de ejemplo no existe
  44. @vicqr JMSSerializerBundle Tres estrategias de exclusión (Exclude, Groups, Versions) Propiedades

    configurables (Virtual Props., Accessors) Eventos para más flexibilidad XML muy configurable Muchas funcionalidades que necesitas siempre listas para usar
  45. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since - Diferentes vistas de un objeto: @Groups
  46. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since - Diferentes vistas de un objeto: @Groups - Limitar nivel de serialización en el grafo: @MaxDepth
  47. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since - Diferentes vistas de un objeto: @Groups - Limitar nivel de serialización en el grafo: @MaxDepth - Exclusión dinámica: @Exclude(if=”...”)
  48. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since - Diferentes vistas de un objeto: @Groups - Limitar nivel de serialización en el grafo: @MaxDepth - Exclusión dinámica: @Exclude(if=”...”) Muchas formas de indicar qué propiedades muestras y cuáles no
  49. @vicqr Propiedades configurables - Cambiar nombre de una propiedad: @SerializedName

    - Crear propiedades virtuales: @VirtualProperty Sencillo cambiar lo que tengo por defecto en las propiedades
  50. @vicqr Accessors - De qué modo hay que acceder las

    propiedades: @AccessorType - Qué método hay que utilizar para acceder una propiedad: @Accessor - En qué orden hay que acceder las propiedades: @AccessorOrder
  51. @vicqr Accessors - De qué modo hay que acceder las

    propiedades: @AccessorType - Qué método hay que utilizar para acceder una propiedad: @Accessor - En qué orden hay que acceder las propiedades: @AccessorOrder Sencillo configurar el acceso a las propiedades
  52. @vicqr XML muy configurable - @XmlRoot - @XmlAttribute - @XmlDiscriminator

    - @XmlValue - @XmlList - @XmlMap - @XmlKeyValuePairs - @XmlAttributeMap - @XmlElement - @XmlNamespace
  53. @vicqr XML muy configurable - @XmlRoot - @XmlAttribute - @XmlDiscriminator

    - @XmlValue - @XmlList - @XmlMap - @XmlKeyValuePairs - @XmlAttributeMap - @XmlElement - @XmlNamespace Hay consenso en que para trabajar con XML es estupendo
  54. @vicqr Eventos para mayor customización - serializer.pre_serialize - serializer.post_serialize -

    serializer.pre_deserialize - serializer.post_deserialize Por ej., para utilizar un servicio (al que no puedes llamar desde la Entidad) http://knpuniversity.com/screencast/symfony-rest3/serialization-event-subscriber
  55. @vicqr Suscribers Los eventos tienen un getVisitor() El visitor es

    el encargado del proceso de serialización Utilizando $visitor->addData() podemos añadir los campos que queramos
  56. @vicqr Suscribers Los eventos tienen un getVisitor() El visitor es

    el encargado del proceso de serialización Utilizando $visitor->addData() podemos añadir los campos que queramos Esta forma de trabajar no encaja mucho con la filosofía del componente Serializer
  57. @vicqr Algún detalle que viene bien saber - Hay que

    solucionar el problema del underscore # app/config/config.yml parameters: jms_serializer.camel_case_naming_strategy.class: JMS\Serializer\Naming\IdenticalPropertyNamingStrategy
  58. @vicqr Algún detalle que viene bien saber - Hay que

    solucionar el problema del underscore # app/config/config.yml parameters: jms_serializer.camel_case_naming_strategy.class: JMS\Serializer\Naming\IdenticalPropertyNamingStrategy https://knpuniversity.com/screencast/symfony-rest
  59. @vicqr Algún detalle que viene bien saber - Hay que

    solucionar el problema del underscore # app/config/config.yml parameters: jms_serializer.camel_case_naming_strategy.class: JMS\Serializer\Naming\IdenticalPropertyNamingStrategy - Los campos null por defecto no se serializan # src/AppBundle/Controller/Api/SpaceshipController.php $context = new SerializationContext(); $context->setSerializeNull(true); return $this->container->get('jms_serializer')->serialize($data, $format, $context); https://knpuniversity.com/screencast/symfony-rest
  60. @vicqr Críticas y elogios frecuentes - Problema licencia - Mantenimiento

    regular - Modelo “caja de herramientas” - Fácil de usar - Permite resolver problemas muy habituales muy cómodamente
  61. @vicqr Componente Serializer No pretende darte soluciones ya hechas para

    todo Solo dos anotaciones (MaxDepth y Groups) Te proporciona algunos normalizadores muy útiles Va mucho de crear tus propios normalizadores Arquitectura potente y flexible que te permite exportar tus estructuras PHP
  62. @vicqr Anotaciones MaxDepth - Detecta y limita el nivel de

    serialización - Especialmente útil serializando árboles grandes
  63. @vicqr Anotaciones MaxDepth - Detecta y limita el nivel de

    serialización - Especialmente útil serializando árboles grandes Groups - Para serializar distintos grupos de atributos de tus entidades - De hecho sirve para implementar cualquiera de los métodos de exclusión
  64. @vicqr Anotaciones - Groups class Spaceship { /** * @Groups({"show",

    "list"}) */ public $name; /** * @Groups({"show"}) */ public $color; /** * @Groups({"show", "list"}) */ public $maxSpeed; }
  65. @vicqr Anotaciones - Groups class Spaceship { /** * @Groups({"show",

    "list"}) */ public $name; /** * @Groups({"show"}) */ public $color; /** * @Groups({"show", "list"}) */ public $maxSpeed; }
  66. @vicqr Anotaciones - Groups $groups = ['groups' => ['list']]; $response

    = new Response($serializer->serialize($spaceship, 'json', $groups), 201); $response->headers->set('Content-Type', 'application/json'); return $response; Así indicamos que queremos serializar el grupo show
  67. @vicqr Setup anotaciones use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Doctrine\Common\Annotations\AnnotationReader; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; $classMetadataFactory

    = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); $normalizer = new ObjectNormalizer($classMetadataFactory); Hay que inicializar classMetadataFactory y pasárselo al normalizador
  68. @vicqr Habilitar cache de Doctrine # app/config/config_prod.yml framework: serializer: cache:

    serializer.mapping.cache.apc El sistema de extracción de metadatos es lento, conviene mucho habilitar la cache cuando se utilizan anotaciones (como Groups)
  69. @vicqr Los principales normalizers disponibles ObjectNormalizer: - El más completo

    - Utiliza el PropertyAccess Component para leer y escribir en el objeto - Normaliza a partir de los métodos get/set/has/remove del objeto
  70. @vicqr Los principales normalizers disponibles ObjectNormalizer: - El más completo

    - Utiliza el PropertyAccess Component para leer y escribir en el objeto - Normaliza a partir de los métodos get/set/has/remove del objeto GetSetMethodNormalizer: - Más sencillo que el anterior - Normaliza llamando a los getters y setters del objeto
  71. @vicqr Los principales normalizers disponibles ObjectNormalizer: - El más completo

    - Utiliza el PropertyAccess Component para leer y escribir en el objeto - Normaliza a partir de los métodos get/set/has/remove del objeto GetSetMethodNormalizer: - Más sencillo que el anterior - Normaliza llamando a los getters y setters del objeto PropertyNormalizer: - Normaliza leyendo directamente las propiedades del objeto
  72. @vicqr Los principales normalizers disponibles ObjectNormalizer: - El más completo

    - Utiliza el PropertyAccess Component para leer y escribir en el objeto - Normaliza a partir de los métodos get/set/has/remove del objeto GetSetMethodNormalizer: - Más sencillo que el anterior - Normaliza llamando a los getters y setters del objeto PropertyNormalizer: - Normaliza leyendo directamente las propiedades del objeto Todos devuelven un mapeo entre valores y nombres de propiedades, la diferencia es cómo lo obtienen
  73. @vicqr Los principales normalizers disponibles ObjectNormalizer: - El más completo

    - Utiliza el PropertyAccess Component para leer y escribir en el objeto - Normaliza a partir de los métodos get/set/has/remove del objeto GetSetMethodNormalizer: - Más sencillo que el anterior - Normaliza llamando a los getters y setters del objeto PropertyNormalizer: - Normaliza leyendo directamente las propiedades del objeto https://symfony.com/doc/current/components/serializer.html#normalizers Todos devuelven un mapeo entre valores y nombres de propiedades, la diferencia es cómo lo obtienen
  74. @vicqr ObjectNormalizer Es muy útil, pero también tiene un coste

    Se apoya en el PropertyAccess Component Ha sido bastante optimizado y siguen optimizándolo
  75. @vicqr ObjectNormalizer Es muy útil, pero también tiene un coste

    Se apoya en el PropertyAccess Component Ha sido bastante optimizado y siguen optimizándolo Si la performance importa, mejor utilizar GetSetMethodNormalizer, PropertyNormalizer o el tuyo propio
  76. @vicqr PropertyAccess Component http://symfony.com/doc/current/components/property_access.html Permite leer de y escribir en

    un objeto de forma cómoda Bien mediante propiedades públicas, setters/getters, hassers/issers Es esto concretamente lo que están intentando optimizar más
  77. @vicqr Creando tus normalizadores use Symfony\Component\Serializer\NameConverter\NameConverterInterface; class OrgPrefixNameConverter implements NameConverterInterface

    { public function normalize($propertyName) { return 'apolo18_'.$propertyName; } public function denormalize($propertyName) { // remove prefix_ prefix return 'apolo18_' === substr($propertyName, 0, 8) ? substr($propertyName, 8) : $propertyName; } } Por ejemplo, para serializar atributos con un nombre distinto
  78. @vicqr Algunas funcionalidades secundarias - setIgnoredAttributes - Boolean functions (is,

    has) - Callbacks Para no serializar algunas propiedades Métodos cuyo resultado booleano se serializa Forma posible de formatear una propiedad
  79. @vicqr Algunas funcionalidades secundarias - setIgnoredAttributes - Boolean functions (is,

    has) - Callbacks Para no serializar algunas propiedades Métodos cuyo resultado booleano se serializa Forma posible de formatear una propiedad Están bien, pero no son imprescindibles
  80. @vicqr Callbacks $callback = function ($logoPath) { return 'thumb_'.$logoPath; };

    $normalizer->setCallbacks(array('logo' => $callback)); Para formatear una propiedad del objeto (por ejemplo, fechas)
  81. @vicqr Referencias circulares Si no haces nada verás un error

    como este: A circular reference has been detected (configured limit: 1). (500 Internal Server Error)
  82. @vicqr Referencias circulares Si no haces nada verás un error

    como este: $normalizer->setCircularReferenceLimit(1); Número de veces que tiene que serializar un objeto antes de considerarlo referencia circular A circular reference has been detected (configured limit: 1). (500 Internal Server Error)
  83. @vicqr Referencias circulares Si no haces nada verás un error

    como este: $normalizer->setCircularReferenceLimit(1); $normalizer->setCircularReferenceHandler(function ($object) { return $object->getName(); }); Número de veces que tiene que serializar un objeto antes de considerarlo referencia circular En lugar de lanzar excepción, la referencia circular es gestionada por este callable A circular reference has been detected (configured limit: 1). (500 Internal Server Error)
  84. @vicqr PropertyInfo Component Extrae información de las propiedades de una

    clase PHP por a partir de metadatos (de Doctrine, PHP Reflection, PHP doc., etc.)
  85. @vicqr Deserializando objetos complejos El Serializer utiliza el componente PropertyInfo

    para esto Hay que pasarle un Extractor al normalizador use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
  86. @vicqr Deserializando objetos complejos El Serializer utiliza el componente PropertyInfo

    para esto Hay que pasarle un Extractor al normalizador use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor()); El Extractor indica de qué modo hay que extraer la información, el PropertyInfo permite al normalizador conocer el tipo de lo que tiene que desnormalizar
  87. @vicqr Críticas y elogios frecuentes - Ciertas cosas muy comunes

    son menos directas que en JMS - XML mal (pobre)
  88. @vicqr ¿Por qué es pobre el XML? El XML puede

    ser bastante más rico que el JSON (namespaces, xincludes, instrucciones de procesado)…
  89. @vicqr ¿Por qué es pobre el XML? El XML puede

    ser bastante más rico que el JSON (namespaces, xincludes, instrucciones de procesado)… Añadir información de un formato a otro no encaja con la filosofía del Serializer
  90. «We want different representations of the same data structure without

    enrichment during the serialization process» Kevin Dunglas https://github.com/symfony/symfony/issues/19330#issuecomment-233515204
  91. @vicqr Críticas y elogios frecuentes - Ciertas cosas muy comunes

    son menos directas que en JMS - XML mal (pobre)
  92. @vicqr Críticas y elogios frecuentes - Ciertas cosas muy comunes

    son menos directas que en JMS - XML mal (pobre) - Flexible, fácil de extender - Potente, permite cubrir necesidades complejas de tu lógica de negocio - Bien mantenido
  93. @vicqr Ha ido mejorando y pretende seguir - Por ejemplo,

    algunas mejoras recientes: - DateTime Normalizer - Data URI Normalizer - CSV y YAML encoders
  94. @vicqr Ha ido mejorando y pretende seguir - Por ejemplo,

    algunas mejoras recientes: - DateTime Normalizer - Data URI Normalizer - CSV y YAML encoders - Conversación continua acerca de cómo mejorar: - http://github.com/symfony/symfony/issues/16179 - http://github.com/symfony/symfony/issues/19330 - http://github.com/symfony/symfony/pull/19374
  95. @vicqr Ha ido mejorando y pretende seguir - Por ejemplo,

    algunas mejoras recientes: - DateTime Normalizer - Data URI Normalizer - CSV y YAML encoders - Conversación continua acerca de cómo mejorar: - http://github.com/symfony/symfony/issues/16179 - http://github.com/symfony/symfony/issues/19330 - http://github.com/symfony/symfony/pull/19374 - API Platform lo usa
  96. @vicqr Ha ido mejorando y pretende seguir - Por ejemplo,

    algunas mejoras recientes: - DateTime Normalizer - Data URI Normalizer - CSV y YAML encoders - Conversación continua acerca de cómo mejorar: - http://github.com/symfony/symfony/issues/16179 - http://github.com/symfony/symfony/issues/19330 - http://github.com/symfony/symfony/pull/19374 - API Platform lo usa Las perspectivas son muy buenas
  97. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

    budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } Quiero llamarlo “mission” No quiero mostrarlo Quiero mostrarlo en el list Quiero añadir “thumb_” Solo en la versión 2 de la API Quiero que sea un campo más
  98. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

    budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } { mission: "Apolo18", email: "[email protected]", logo: "thumb_logo.jpg", spaceship: "Orion" } En el show
  99. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

    budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } { mission: "Apolo18", email: "[email protected]", logo: "thumb_logo.jpg", spaceship: "Orion" } En el list
  100. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

    budget: "USD 6 billion", email: "[email protected]", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } { mission: "Apolo18", email: "[email protected]", logo: "thumb_logo.jpg", twitter: "apolo18", spaceship: "Orion" } En la versión 2
  101. @vicqr Serialicemos nuestra misión espacial - Renombrar propiedades - Exponer

    solo las que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre
  102. @vicqr Con JMSSerializerBundle - Renombrar propiedades - Exponer solo las

    que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre @SerializedName @ExclusionStrategy, etc. @Groups @Accesor @Until, @Since @VirtualProperty
  103. @vicqr Con JMSSerializerBundle - Renombrar propiedades - Exponer solo las

    que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre @SerializedName @ExclusionStrategy, etc. @Groups @Accesor @Until, @Since @VirtualProperty No hay problema @Type - ¿Serializar objetos encadenados? - ¿Deserializar objetos encadenados?
  104. @vicqr Con Symfony Serializer - Renombrar propiedades - Exponer solo

    las que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre Un getter nuevo @Groups @Groups Un getter nuevo @Groups Un getter nuevo
  105. @vicqr Con Symfony Serializer - Renombrar propiedades - Exponer solo

    las que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre Un getter nuevo @Groups @Groups Un getter nuevo @Groups Un getter nuevo O escribir tus normalizers, cuando quieras
  106. @vicqr Con Symfony Serializer - Renombrar propiedades - Exponer solo

    las que quiero - Tener distintas representaciones - Modificar el valor de una propiedad - Tener distintas versiones de la API - Que spaceship sea solo un nombre Un getter nuevo @Groups @Groups Un getter nuevo @Groups Un getter nuevo O escribir tus normalizers, cuando quieras Ojo referencias circulares Pasar Extractor - ¿Serializar objetos encadenados? - ¿Deserializar objetos encadenados?
  107. Más que verlo como “cuál es mejor” hay que entender

    que son dos animales distintos https://www.flickr.com/photos/5of7/5531923725
  108. @vicqr Síntesis de críticas y puntos fuertes Licencia Mantenimiento Flexibilidad

    Curva aprendizaje Out-of-the-box XML JMSSERIALIZERBUNDLE SYMFONY SERIALIZER
  109. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Quiero “marranear” en el proceso de serialización? Debería usar JMS
  110. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS
  111. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Las transformaciones que quiero hacer son bastante comunes? No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS
  112. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Las transformaciones que quiero hacer son bastante comunes? Sí Quizá sea más rápido usar JMS No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS
  113. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Las transformaciones que quiero hacer son bastante comunes? Sí Quizá sea más rápido usar JMS No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS No El componente Serializer me vendrá muy bien
  114. @vicqr ¿Y la performance? - Son parecidos - En el

    Symfony Serializer lo más lento es el ObjectNormalizer - Aunque se ha hecho más rápido y sigue siendo optimizado
  115. @vicqr ¿Y la performance? - Son parecidos - En el

    Symfony Serializer lo más lento es el ObjectNormalizer - Aunque se ha hecho más rápido y sigue siendo optimizado https://github.com/symfony/symfony/issues/16179 Discusión y comparativas
  116. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Las transformaciones que quiero hacer son bastante comunes? Sí Quizá sea más rápido usar JMS No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS No El componente Serializer me vendrá muy bien
  117. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Las transformaciones que quiero hacer son bastante comunes? Sí Quizá sea más rápido usar JMS No ¿Quiero “marranear” en el proceso de serialización? Sí Conviene que use JMS Debería usar JMS No El componente Serializer me vendrá muy bien ¿La performance importa mucho? Puedo usar el ObjectNormalizer Debería usar otro o hacerme el mío No Sí
  118. @vicqr Experiencia personal 1. Hace años prefería JMSSerializer 2. En

    algún momento encontré algo que no supe cómo hacer y cambié 3. La primera impresión con SfSerializer fue que era costoso 4. A día de hoy prefiero SfSerializer 5. Si tengo que hacer algo rápido cojo JMSSerializer
  119. @vicqr Experiencia personal 1. Hace años prefería JMSSerializer 2. En

    algún momento encontré algo que no supe cómo hacer y cambié 3. La primera impresión con SfSerializer fue que era costoso 4. A día de hoy prefiero SfSerializer 5. Si tengo que hacer algo rápido cojo JMSSerializer Por lo que he visto por ahí, es una evolución bastante común
  120. @vicqr Qué recordar El serializador nos facilita crear distintas representaciones

    de los objetos Tanto el bundle como el componente son dos muy buenas herramientas Son DISTINTAS, están enfocadas diferente y son óptimas para distintos casos
  121. @vicqr Qué recordar El serializador nos facilita crear distintas representaciones

    de los objetos Tanto el bundle como el componente son dos muy buenas herramientas Son DISTINTAS, están enfocadas diferente y son óptimas para distintos casos El JMSSerializer te da más “hecho” El componente Serializer te facilita más montar lo que necesites
  122. @vicqr Resumen en un comentario de Github Just saying, but

    to me the Symfony's serializer does not especially suffer from a bad design, especially because its philosophy is far from the JMS serializer one. The idea of the Symfony's serializer is to keep things simple, not trying to answer every use-cases natively, but instead providing a great and simple architecture. Despite the fact it offers some great features, I'm almost never using the ObjectNormalizer and rather rely on custom normalizers (sometimes encoders) for each of my needs. Because when I'm writing code for my application, I know exactly what the output should be. I do not need something answering everything, just good and simple interfaces over it. This is way less brainfucking than a JMS Serializer, as soon as you're not trying to answer very generic needs. Now I can understand some of your concerns if you need to handle things in a very generic way, but to me there is nothing impossible with the current architecture regarding this. But anyway, I don't think the Symfony's serializer should try to replace entirely a JMS Serializer. Those are simply two different tools. Use or don't use them. https://github.com/symfony/symfony/issues/19330#issuecomment-233405451
  123. ¡Con el Serializer no puedo hacer XMLs decentes! ¡El JMS

    es una basura! ¡¿Para qué quieres normalizadores y encoders?!
  124. ¡Con el Serializer no puedo hacer XMLs decentes! ¡El JMS

    es una basura! ¡¿Para qué quieres normalizadores y encoders?! ¡Deshonras a tu familia utilizando ese código!