You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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数组,无需额外包装类,具体实现步骤如下:

  1. 修正DTO类型错误
    注意你的DTO中description字段被定义为int,但JSON payload里该字段是字符串类型,这会导致映射失败,先修正类型匹配:

    <?php
    
    class MyDto {
     public function __construct(
       public readonly int $number,
       public readonly string $description,
     ) {}
    }
    
  2. 控制器参数声明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);
        }
    }
    
  3. 实现原理
    MapRequestPayload会根据参数的类型提示自动处理:当参数声明为DTO数组时,它会将请求体的JSON数组逐个解析,调用DTO的构造函数完成实例化,最终生成DTO对象数组。只要DTO的构造函数参数名与JSON字段名一致、类型兼容,就能自动完成映射。

内容的提问来源于stack exchange,提问作者zangetsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:58:17