Nuevo en Symfony 4.1: mejoras relacionadas con el Serializer
Añadido un ConstraintViolationListNormalizer
Cuando se trabajan con APIs en aplicaciones Symfony, es habitual utilizar un código como el siguiente:
/** * @Route("/blog/new", name="api_blog_new") * @Method("POST") * @Security("is_granted('ROLE_ADMIN')") */ public function new(Request $request, SerializerInterface $serializer, ValidatorInterface $validator) { $data = $request->getContent(); $post = $serializer->deserialize($data, Post::class, 'json', ['groups' => ['post_write']]); $post->setAuthor($this->getUser()); $violations = $validator->validate($post); if (count($violations) > 0) { $repr = $serializer->serialize($violations, 'json'); return JsonResponse::fromJsonString($repr, 400); } // ... }
La variable $violations
contiene un objeto de tipo ConstraintViolationList
y
es habitual transformarlo en una lista de errores que se serializa e incluye en
la respuesta JSON. Por eso en Symfony 4.1 hemos añadido una clase
ConstraintViolationListNormalizer
que hace eso por ti automáticamente. El
normalizador sigue el estándar RFC 7807 para generar la lista de errores.
Esta funcionalidad fue contribuida por Grégoire Pineau en el pull request #22150.
Obtener los resultados XML y CSV como colecciones
Los encoders CsvEncoder
y XmlEncoder
ahora definen una nueva opción de
configuración llamada as_collection
. Si pasas esa opción a true
como parte
del contexto de los encoders, los resultados se devuelven como una colección.
Esta funcionalidad fue contribuida por Hamza Amrouche en los pull requests #25218 y #25369.
Argumentos por defecto para la denormalización
Si el constructor de una clase define argumentos, tal y como sucede habitualmente
cuando se utilizan value objects, el serializar no es capaz de construir el
objeto. En Symfony 4.1 hemos añadido una opción llamada default_constructor_arguments
para solucionar este problema.
En el siguiente ejemplo, tanto foo
como bar
son requeridos por el
constructor, pero solo se define explícitamente el valor de foo
. El valor de
bar
se obtiene mediante la opción default_constructor_arguments
:
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; class MyObj { private $foo; private $bar; public function __construct($foo, $bar) { $this->foo = $foo; $this->bar = $bar; } } $normalizer = new ObjectNormalizer($classMetadataFactory); $serializer = new Serializer(array($normalizer)); // equivalente a $data = new MyObj('Hello', ''); $data = $serializer->denormalize(['foo' => 'Hello'], 'MyObj', [ 'default_constructor_arguments' => [ 'MyObj' => ['foo' => '', 'bar' => ''], ] ]);
Esta funcionalidad fue contribuida por Maxime Veber en el pull request #25493.
Añadido un handler para MaxDepth
En ocasiones, en vez de parar la serialización cuando se alcanza el máximo nivel de anidamiento configurado, es mejor dejar que sea la aplicación la que decida cómo gestionar esta situación.
En Symfony 4.1 puedes resolver este problema definiendo un handler con el
método setMaxDepthHandler()
:
use Doctrine\Common\Annotations\AnnotationReader; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Annotation\MaxDepth; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; class Foo { public $id; /** @MaxDepth(1) */ public $child; } $level1 = new Foo(); $level1->id = 1; $level2 = new Foo(); $level2->id = 2; $level1->child = $level2; $level3 = new Foo(); $level3->id = 3; $level2->child = $level3; $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); $normalizer = new ObjectNormalizer($classMetadataFactory); $normalizer->setMaxDepthHandler(function ($foo) { return '/foos/'.$foo->id; }); $serializer = new Serializer(array($normalizer)); $result = $serializer->normalize($level1, null, array(ObjectNormalizer::ENABLE_MAX_DEPTH => true)); /* $result = array[ 'id' => 1, 'child' => [ 'id' => 2, 'child' => '/foos/3', ] ]; */
Esta funcionalidad fue contribuida por Kévin Dunglas en el pull request #26108.
Ignorar los comentarios cuando se decodifica XML
En las versiones anteriores de Symfony, los comentarios XML se procesaban al decodificar los contenidos. En Symfony 4.1, los comentarios XML se eliminan por defecto, pero puedes controlar este comportamiento con un nuevo argumento del constructor:
class XmlEncoder { public function __construct( string $rootNodeName = 'response', int $loadOptions = null, array $ignoredNodeTypes = array(XML_PI_NODE, XML_COMMENT_NODE) ) { // ... } }
Esta funcionalidad fue contribuida por James Sansbury en el pull request #26445.
Fuente: New in Symfony 4.1: Serializer improvements
Comentarios
Proyectos Symfony destacados
La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más
Síguenos en @symfony_es para acceder a las últimas noticias.