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

Symfony使用@ParamConverter传递保留原键的关联数组对象参数

Symfony FOSRest @ParamConverter 保留请求自定义键名转换对象数组解决方案

问题原因

默认使用array<MyClass>作为反序列化类型时,序列化器会将关联数组转为索引数组,丢失原请求的自定义键名,需要使用标识键值对结构的类型声明告知序列化器保留键。

方案1:修改序列化类型注解(推荐,适配新版本)

直接修改控制器的@ParamConverter注解和参数声明即可实现需求,无需额外开发:

/**
 * @OA\Post(
 *     path="/post-my-class",
 *     @OA\RequestBody(
 *          required=true,
 *          @OA\JsonContent(
 *               ref="#/components/schemas/MyClass"
 *          )
 *     )
 *)
 * 关键修改:在class属性中指定数组键类型为string,告知序列化器保留原键
 * @ParamConverter("arrayOfObjects", class="array<string, MyService\MyClass>", converter="fos_rest.request_body")
 *
 * @Route("/post-my-class", methods="POST")
 * @param array<string, MyClass> $arrayOfObjects
 *
 * @return Response
 */
public function postController(array $arrayOfObjects): Response
{
   // 此时$arrayOfObjects已经是保留id_1、id_2等自定义键,值为MyClass对象的关联数组
}

如果以上配置不生效,大概率是项目使用了JMSSerializer,将类型改为JMSSerializer专用的字典类型即可:

@ParamConverter("arrayOfObjects", class="Dictionary<string, MyService\MyClass>", converter="fos_rest.request_body")

方案2:手动转换(兼容性最强,适配所有版本)

如果版本不支持上述类型声明,可以先拿到保留键的原始数组,再手动批量转换为对象:

/**
 * @ParamConverter("arrayOfObjects", class="array", converter="fos_rest.request_body")
 *
 * @Route("/post-my-class", methods="POST")
 * @param array $arrayOfObjects
 */
public function postController(array $arrayOfObjects, \Symfony\Component\Serializer\SerializerInterface $serializer): Response
{
    // 手动将每个数组值转为MyClass对象,完全保留原请求键名
    $arrayOfObjects = array_map(function (array $item) use ($serializer) {
        return $serializer->denormalize($item, MyClass::class);
    }, $arrayOfObjects);

    // 后续业务逻辑直接使用$arrayOfObjects即可
}

如果项目用的是JMSSerializer,注入JMS\Serializer\SerializerInterface,调用$serializer->fromArray($item, MyClass::class)完成转换即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:00:06