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.

281604c1a5357a164f2a9cd6e403b4e3?s=128

Victoria Quirante

July 01, 2017
Tweet

Transcript

  1. None
  2. None
  3. 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 victoria@limenius.com
  4. INTRODUCCIÓN De qué va todo esto http://www.flickr.com/photos/lilianasaeb/16463233379

  5. ¿Qué es serializar?

  6. @vicqr Serialización Es el proceso de codificación de un objeto

    en otro formato que puede ser almacenado, transmitido y posteriormente descodificado
  7. @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..)
  8. @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
  9. @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
  10. @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)
  11. @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)
  12. @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)
  13. @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
  14. @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
  15. @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
  16. @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
  17. ¿A qué llamamos serializador?

  18. @vicqr El serializador Es un código que es muy bueno

    serializando por nosotros
  19. @vicqr El serializador Es un código que es muy bueno

    serializando por nosotros
  20. El verdadero problema que nos ayuda a resolver

  21. Los objetos y las representaciones que queremos pueden ser muy

    distintos
  22. @vicqr Representaciones != lo que hay en la BD {

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

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

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

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

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "apolo18@nasa.es", 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_”
  27. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "apolo18@nasa.es", 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
  28. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "apolo18@nasa.es", 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
  29. @vicqr Representaciones != lo que hay en la BD {

    id: 18, name: "Apolo18", budget: "USD 6 billion", email: "apolo18@nasa.es", 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
  30. VISTAZO GENERAL A ambas soluciones

  31. @vicqr Datos básicos JMSSERIALIZERBUNDLE SYMFONY SERIALIZER

  32. @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
  33. @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
  34. @vicqr Inciso: componentes y bundles - Componente -> librería desacoplada

    y reutilizable - Bundle -> atado al Symfony Framework
  35. @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 +
  36. @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 +
  37. @vicqr JMSSerialiazerBundle - Características - Muchas anotaciones útiles que cubren

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

    require - Registrar el bundle http://jmsyst.com/bundles/JMSSerializerBundle
  39. @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
  40. @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
  41. @vicqr Componente Serializer - Características

  42. @vicqr Componente Serializer - Características El trabajo más complejo se

    lleva a cabo en los normalizadores
  43. @vicqr SF Serializer - Instalación y setup - Instalación: -

    composer require - Si quieres usar ObjectNormalizer instalas también PropertyAccess
  44. @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
  45. @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);
  46. @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
  47. TRABAJANDO CON AMBOS Serialicemos algo fácil

  48. http://github.com/VictoriaQ/sf-serialization-talk

  49. @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!"); }
  50. @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!"); }
  51. @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); }
  52. @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); }
  53. @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}
  54. @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!"); }
  55. @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!"); }
  56. @vicqr Deserializar un objeto ya existente # AppBundle/Controller/Api/SpaceshipController.php $serializer->deserialize($request->getContent(), Spaceship::class,

    'json', array('object_to_populate' => $spaceship));
  57. @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); }
  58. @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
  59. @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
  60. JMSSERIALIZERBUNDLE EN DETALLE http://www.flickr.com/photos/florianric/7263382550

  61. @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
  62. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose
  63. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since
  64. @vicqr Estrategias de exclusión - Estrategias generales: @ExclusionPolicy (all, none),

    @Exclude, @Expose - Versiones: @Until, @Since - Diferentes vistas de un objeto: @Groups
  65. @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
  66. @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=”...”)
  67. @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
  68. @vicqr Propiedades configurables - Cambiar nombre de una propiedad: @SerializedName

    - Crear propiedades virtuales: @VirtualProperty
  69. @vicqr Propiedades configurables - Cambiar nombre de una propiedad: @SerializedName

    - Crear propiedades virtuales: @VirtualProperty Sencillo cambiar lo que tengo por defecto en las propiedades
  70. @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
  71. @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
  72. @vicqr XML muy configurable - @XmlRoot - @XmlAttribute - @XmlDiscriminator

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

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

    serializer.pre_deserialize - serializer.post_deserialize
  75. @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
  76. @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
  77. @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
  78. @vicqr Deserializando objetos complejos Utilizamos la anotación @Type para que

    el serializer sepa qué objeto es cada uno
  79. @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
  80. @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
  81. @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
  82. @vicqr Críticas y elogios frecuentes - Problema licencia - Mantenimiento

    regular - Modelo “caja de herramientas”
  83. @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
  84. COMPONENTE SERIALIZER EN DETALLE

  85. @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
  86. @vicqr Anotaciones MaxDepth - Detecta y limita el nivel de

    serialización - Especialmente útil serializando árboles grandes
  87. @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
  88. @vicqr Anotaciones - Groups class Spaceship { /** * @Groups({"show",

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

    "list"}) */ public $name; /** * @Groups({"show"}) */ public $color; /** * @Groups({"show", "list"}) */ public $maxSpeed; }
  90. @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
  91. @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
  92. @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)
  93. @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
  94. @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
  95. @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
  96. @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
  97. @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
  98. @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
  99. @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
  100. @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
  101. Utilizar el Symfony Serializer va mucho de crear tus propios

    normalizadores
  102. @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
  103. @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
  104. @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
  105. @vicqr Callbacks $callback = function ($logoPath) { return 'thumb_'.$logoPath; };

    $normalizer->setCallbacks(array('logo' => $callback)); Para formatear una propiedad del objeto (por ejemplo, fechas)
  106. @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)
  107. @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)
  108. @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)
  109. @vicqr Deserializando objetos complejos El Serializer utiliza el componente PropertyInfo

    para esto
  110. @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.)
  111. @vicqr Deserializando objetos complejos El Serializer utiliza el componente PropertyInfo

    para esto Hay que pasarle un Extractor al normalizador
  112. @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());
  113. @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
  114. @vicqr Críticas y elogios frecuentes - Ciertas cosas muy comunes

    son menos directas que en JMS - XML mal (pobre)
  115. ¿Y por qué lo del XML no está “bien hecho”

    en el Serializer?
  116. @vicqr ¿Por qué es pobre el XML? El XML puede

    ser bastante más rico que el JSON (namespaces, xincludes, instrucciones de procesado)…
  117. @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
  118. «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
  119. @vicqr Críticas y elogios frecuentes - Ciertas cosas muy comunes

    son menos directas que en JMS - XML mal (pobre)
  120. @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
  121. @vicqr Ha ido mejorando y pretende seguir - Por ejemplo,

    algunas mejoras recientes: - DateTime Normalizer - Data URI Normalizer - CSV y YAML encoders
  122. @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
  123. @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
  124. @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
  125. Serialicemos algo menos fácil TRABAJANDO CON AMBOS

  126. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

    budget: "USD 6 billion", email: "apolo18@nasa.es", 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
  127. @vicqr Serialicemos nuestra misión espacial { id: 18, name: "Apolo18",

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

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

    budget: "USD 6 billion", email: "apolo18@nasa.es", logo: "logo.jpg", twitter: "apolo18", spaceship: { id: 29, name: "Orion" } } { mission: "Apolo18", email: "apolo18@nasa.es", logo: "thumb_logo.jpg", twitter: "apolo18", spaceship: "Orion" } En la versión 2
  130. @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
  131. @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
  132. @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?
  133. @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
  134. @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
  135. @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?
  136. COMPARANDO ¿Entonces cuál uso?

  137. Pues depende, los dos están muy bien

  138. Pues depende, los dos están muy bien

  139. Pues depende, los dos están muy bien

  140. Más que verlo como “cuál es mejor” hay que entender

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

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

  143. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    Debería usar JMS
  144. @vicqr Casos de uso ¿Quiero trabajar bastante con XML? Sí

    No ¿Quiero “marranear” en el proceso de serialización? Debería usar JMS
  145. @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
  146. @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
  147. @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
  148. @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
  149. @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
  150. @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
  151. @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
  152. @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í
  153. @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
  154. @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
  155. APUNTES FINALES Qué recordar

  156. @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
  157. @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
  158. @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
  159. None
  160. ¡Con el Serializer no puedo hacer XMLs decentes!

  161. ¡Con el Serializer no puedo hacer XMLs decentes! ¡El JMS

    es una basura!
  162. ¡Con el Serializer no puedo hacer XMLs decentes! ¡El JMS

    es una basura! ¡¿Para qué quieres normalizadores y encoders?!
  163. ¡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!
  164. Consultoría, formación y desarrollo @limenius @vicqr victoria@limenius.com ¡Gracias! Organizamos React

    Alicante 28-30 Sep. 2017 @ReactAlicante