使用 FOSRestBundle 将 POST 请求主体序列化为数组

Serialize POST request body into array with FOSRestBundle

我正在尝试使用 Symfony 3 和 FOSRestBundle 制作 Rest 网络服务。
我来自 Spring + Jackson 背景,所以我正在努力做到这一点,以便您可以将对象作为请求主体传递给控制器​​,请求主体成为函数参数,return 对象被序列化为 json,到目前为止,我设法让它适用于除数组以外的所有内容。
这是我的代码:

配置:

#FOSRestBundle
fos_rest:
    param_fetcher_listener: true
    body_listener: 
        enabled: true
        decoders:
            json: fos_rest.decoder.json
    format_listener:
        rules:
            - { path: ^/, priorities: [ json ], fallback_format: json, prefer_extension: true }

    body_converter:
        enabled: true
        #validate: true

    view:
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
        view_response_listener: 'force'
        formats:
            xml:  false
            json: true
        templating_formats:
            html: true

    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
    allowed_methods_listener: true
    access_denied_listener:
        json: true

这是控制器

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use JMS\DiExtraBundle\Annotation\Inject;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

class DefaultController extends FOSRestController {

    /**
     * @Post("/rest", name="rest_test")
     * @ParamConverter("myArr", converter="fos_rest.request_body")
     * @View
     * @param Request $request
     */
    public function restAction(Request $request, array $myArr) {
        return $myArr;
    }
}

当我尝试从我的休息客户端调用它时(将 [1, 2] 作为请求正文)我收到此错误:

{
  "code": 500,
  "message": "Converter 'fos_rest.request_body' does not support conversion of parameter 'myArr'."
}

如果我将 myArr 变成一个对象(即我将其类型从 array 更改为 MyObject,包含 number 变量 myVar)并发送反映该对象结构的数据(例如 {"myVar": 2} )它工作正常,但不适用于数组。

FOS Rest 主体转换器的目的是填充对象,而不是数组。你可以尝试实现你自己的参数转换器(see this documentation),但我真的不确定你能否实现你想要的。

无论如何,处理对象不是更干净吗?它可以让您确保收到的数据符合您的预期,使用验证等等...

经过几天的代码编写以及与 FoS 的一位合作者的愉快对话 https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1582 我发现,如果您使用的是 JMS 序列化程序包,则只需编写 array 在参数转换器的 class 字段中,它将反序列化为一个数组。我想我应该早点尝试

@ParamConverter("myarr", class="array", converter="fos_rest.request_body")

它甚至可以反序列化对象数组(只要它们相同 class,我猜)

@ParamConverter("myarr", class="array<Namespace/Class>", converter="fos_rest.request_body")

更新 我正在更新这个答案,因为我停止使用 JMS Serializer 并开始使用 Symfony Serializer,它对对象数组有不同的语法:

@ParamConverter("myarr", class="Namespace/Class[]", converter="fos_rest.request_body")

普通数组语法未受影响