Added a ConstraintViolationListNormalizer
¶
Contributed by
Grégoire Pineau
in #22150.
When working on APIs with Symfony, it's common to use code like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * @Route("/blog/new", name="api_blog_new") * @Method("POST") * @Security("is_granted('ROLE_ADMIN')") */publicfunctionnew(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');returnJsonResponse::fromJsonString($repr,400);}// ...} |
The $violations
variable contains a ConstraintViolationList
object and
it's common to transform it into a list of errors and serialize the list to
include it in a JSON response. That's why in Symfony 4.1 we've added aConstraintViolationListNormalizer
which does that for you automatically.
The normalizer follows the RFC 7807 specification to generate the list of
errors.
Getting the XML and CSV results as a collection¶
Contributed by
Hamza Amrouche
in #25218 and#25369.
The CsvEncoder
and XmlEncoder
now define a new config option calledas_collection
. If you pass that option as part of the context argument and
set it to true
, the results will be a collection.
Default constructor arguments for denormalization¶
Contributed by
Maxime Veber
in #25493.
If the constructor of a class defines arguments, as usually happens when using
Value Objects, the serializer won't be able to create the object. In Symfony 4.1
we've introduced a new default_constructor_arguments
context option to
solve this problem.
In the following example, both foo
and bar
are required constructor
arguments but only foo
is provided. The value of bar
is taken from thedefault_constructor_arguments
option:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | useSymfony\Component\Serializer\Serializer;useSymfony\Component\Serializer\Normalizer\ObjectNormalizer;classMyObj{private$foo;private$bar;publicfunction__construct($foo,$bar){$this->foo=$foo;$this->bar=$bar;}}$normalizer=newObjectNormalizer($classMetadataFactory);$serializer=newSerializer(array($normalizer));// this is equivalent to $data = new MyObj('Hello', '');$data=$serializer->denormalize(['foo'=>'Hello'],'MyObj',['default_constructor_arguments'=>['MyObj'=>['foo'=>'','bar'=>''],]]); |
Added a MaxDepth
handler¶
Contributed by
Kévin Dunglas
in #26108.
Sometimes, instead of just stopping the serialization process when the configured max depth is reached, it's better to let the developer handle this situation to return something (e.g. the identifier of the entity).
In Symfony 4.1 you can solve this problem defining a custom handler with the newsetMaxDepthHandler()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | useDoctrine\Common\Annotations\AnnotationReader;useSymfony\Component\Serializer\Serializer;useSymfony\Component\Serializer\Annotation\MaxDepth;useSymfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;useSymfony\Component\Serializer\Mapping\Loader\AnnotationLoader;useSymfony\Component\Serializer\Normalizer\ObjectNormalizer;classFoo{public$id;/** @MaxDepth(1) */public$child;}$level1=newFoo();$level1->id=1;$level2=newFoo();$level2->id=2;$level1->child=$level2;$level3=newFoo();$level3->id=3;$level2->child=$level3;$classMetadataFactory=newClassMetadataFactory(newAnnotationLoader(newAnnotationReader()));$normalizer=newObjectNormalizer($classMetadataFactory);$normalizer->setMaxDepthHandler(function($foo){return'/foos/'.$foo->id;});$serializer=newSerializer(array($normalizer));$result=$serializer->normalize($level1,null,array(ObjectNormalizer::ENABLE_MAX_DEPTH=>true));/*$result = array['id' => 1,'child' => ['id' => 2,'child' => '/foos/3', ]];*/ |
Ignore comments when decoding XML¶
Contributed by
James Sansbury
in #26445.
In previous Symfony versions, XML comments were processed when decoding contents. Also, if the first line of the XML content was a comment, it was used as the root node of the decoded XML.
In Symfony 4.1, XML comments are removed by default but you can control this behavior with the new optional third constructor argument:
1 2 3 4 5 6 7 8 9 10 | classXmlEncoder{publicfunction__construct(string$rootNodeName='response',int$loadOptions=null,array$ignoredNodeTypes=array(XML_PI_NODE,XML_COMMENT_NODE)){// ...}} |