Quantcast
Channel: Symfony Blog
Viewing all articles
Browse latest Browse all 3059

New in Symfony 4.1: Serializer improvements

$
0
0

Added a ConstraintViolationListNormalizer

Grégoire Pineau

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

Hamza Amrouche

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

Maxime Veber

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

Kévin Dunglas

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

James Sansbury

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)){// ...}}

Be trained by Symfony experts - 2018-04-23 Lyon - 2018-04-23 Lyon - 2018-04-25 Clichy

Viewing all articles
Browse latest Browse all 3059

Trending Articles