添加了一个 ConstraintViolationListNormalizer
Contributed by
Grégoire Pineau
in #22150.
用 Symfony 操作 APIs 时,下面的代码很常见:
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')")
*/
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);
}
// ...
} |
$violations
变量包括了一个 ConstraintViolationList
对象,它常被转换成一个错误列表,再把列表序列化成一个包含 error的 JSON 响应。这就是为何在 Symfony 4.1 中我们添加了一个 ConstraintViolationListNormalizer
来帮你自动处理的原因。normalizer遵循 RFC 7807 协议来生成错误列表。
把 XML 和 CSV 结果获取为collection
Contributed by
Hamza Amrouche
in #25218 and
#25369.
CsvEncoder
和 XmlEncoder
现在定义了一个新的名为 as_collection
的配置选项。如果把此选项作为上下文的一部分传入参数,并把它设为 true
,则结果就会是一个结果集。
denormalization时默认的构造器参数
Contributed by
Maxime Veber
in #25493.
如果一个类的构造器中定义了参数,一般在使用一个 Value对象 时,serializer 无法创建这个对象。在 Symfony 4.1 中,我们引入了全新的 default_constructor_arguments
上下文选项,来解决此问题。
下例中, foo
和 bar
都需要构造器参数,但只有 foo
提供了。 bar
则是由
default_constructor_arguments
选项获取到:
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 | 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));
// this is equivalent to $data = new MyObj('Hello', '');
// 这等同于 $data = new MyObj('Hello', '');
$data = $serializer->denormalize(['foo' => 'Hello'], 'MyObj', [
'default_constructor_arguments' => [
'MyObj' => ['foo' => '', 'bar' => ''],
]
]); |
添加了一个 MaxDepth handler
Contributed by
Kévin Dunglas
in #26108.
在达到所配置的最大深度时,有时并不需要停止序列化的进程 ,更好的方式是让开发者处理这种情况,返回一些东西 (如,entity的识别符)。
在 Symfony 4.1 中你可以解决这个问题,用全新的 setMaxDepthHandler()
方法自定义一个 handler:
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 | 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',
]
];
*/ |
在 decoding XML 时忽略注释
Contributed by
James Sansbury
in #26445.
在之前的 Symfony 版本中,XML 组件在 decoding 内容时被调用。同时,如果 XML 的第一行是注释,它会被视为反解出的 XML 的根结点。
在 Symfony 4.1 中,XML 注释默认被移除了,但你可以用新的、可选的第三个参数来控制这种行为: