如何在Symfony中用MapRequestPayload映射JSON数组到DTO数组
问题描述
我正在使用Symfony框架,当前传入的JSON payload格式如下:
[ { "number": 1, "description": "Test 1" }, { "number": 2, "description": "Test 2" }, { "number": 3, "description": "Test 3" } ]
我定义了如下的Data Transfer Object(DTO):
<?php class MyDto { public function __construct( public readonly int $number, public readonly int $description, ) {} }
我的目标是在Symfony控制器中将JSON对象数组直接映射为MyDto对象数组。当前我的控制器方法如下:
public function index(#[MapRequestPayload] MyDto $dto) { ... }
我希望找到一种无需创建额外DTO来包装数据的方式,直接完成JSON对象数组到MyDto对象数组的映射。Symfony中是否有内置或高效的实现方法?
解决方案
Symfony的#[MapRequestPayload]属性原生支持直接映射DTO数组,无需额外包装类,具体实现步骤如下:
修正DTO类型错误
注意你的DTO中description字段被定义为int,但JSON payload里该字段是字符串类型,这会导致映射失败,先修正类型匹配:<?php class MyDto { public function __construct( public readonly int $number, public readonly string $description, ) {} }控制器参数声明DTO数组类型
在控制器方法的参数中,将单一MyDto类型改为数组类型(PHP 8.0+推荐使用array<MyDto>,PHP 7.4+可使用MyDto[]),同时保留#[MapRequestPayload]属性:public function index(#[MapRequestPayload] array<MyDto> $dtoList) { // $dtoList即为MyDto对象组成的数组,可直接遍历使用 foreach ($dtoList as $item) { // 示例操作:输出每个DTO的属性 echo sprintf("%d: %s\n", $item->number, $item->description); } }实现原理
MapRequestPayload会根据参数的类型提示自动处理:当参数声明为DTO数组时,它会将请求体的JSON数组逐个解析,调用DTO的构造函数完成实例化,最终生成DTO对象数组。只要DTO的构造函数参数名与JSON字段名一致、类型兼容,就能自动完成映射。
内容的提问来源于stack exchange,提问作者zangetsu
相关产品推荐
相关产品推荐

