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
相关产品推荐
相关产品推荐

