首页 > 解决方案 > 为什么/如何工作:Symfony 2.8 + FOSRestBundle 自动反序列化请求对象

问题描述

我正在迁移一个Symfony 2.8我没有创建的现有文件。以前的开发人员无法回答问题。

大多数代码很容易理解,但有一点我根本无法弄清楚它是如何工作的:

控制器/动作参数会自动从JSON数据反序列化为自定义对象。这没什么特别的,我不明白 Symfony 是如何/在哪里被告知要做什么的。从我的角度来看,重要的配置数据丢失了,但它仍然有效。

没关系,但是在不理解它为什么在这种情况下工作的情况下,我无法弄清楚为什么在将项目迁移到Symfony 3.4...时它不再工作了

对不起(非常)长的问题,但我尝试了不同的方法来解决问题并回答问题,但它们都导致了不同的问题......

使用以下捆绑包

sensio/framework-extra-bundle       v3.0.29
friendsofsymfony/rest-bundle        2.4.0
jms/serializer                      1.13.0 
jms/serializer-bundle               1.5.0 

配置:

// app/config/config.yml
sensio_framework_extra:
    request: { converters: true }

fos_rest:
    ...
    body_converter:
        enabled: true

#jms_serializer:  (not configured)
#    ...

代码:

// src/AppBundle/Util/SortInfo.php
class SortInfo {
    public $sortOrder;
    public $sortBy;
}


// src/AppBundle/Resources/serializer/Util.SortInfo.yml
AppBundle\Util\SortInfo:
    exclusion_policy: ALL
    properties:
        sortOrder:
            type: string
            expose: true
        sortBy:
            type: string
            expose: true

// src/AppBundle/Controller/SortingController.php
class SortingController extends Controller {
    ...

    /**
     * @FOSRest\View()
     */
    public function sortAction(SortInfo $sortInfo) {
        $this->logger->info("sortAction");
        $this->logger->info("   ".gettype($sortInfo)."  --  ".get_class($sortInfo));
        $this->logger->info("   ".$sortInfo->sortOrder."  --  ".$sortInfo->sortBy);

        ...
    }     
}

而已。在挖掘了几个小时后,我找不到任何明确的配置来告诉sortAction方法自动转换JSON来自请求的数据。但它有效。

具有以下JSON内容的请求会导致以下日志输出:

// JSON content
{"sortOrder":"ASC", "sortBy":"name"}

// Log output
sortAction
    object  --  AppBundle\Util\SortInfo
    ASC  --  name

为什么这行得通?

如前所述,这很好,但问题是,相同的代码不适用于Symfony 3.4新版本的 FOSRest、ExtrasBundle 和 JMSSerializer:

sensio/framework-extra-bundle       v5.2.4
friendsofsymfony/rest-bundle        2.5.0
jms/serializer                      2.1.0
jms/serializer-bundle               3.0.0 

具有相同JSON数据的请求会在 `Symfony 3.4' 中产生以下日志输出:

// Log output
sortAction
    object  --  AppBundle\Util\SortInfo
      --  

因此,虽然SortInfo创建了(非空),但sortBysortOrder属性为空/空。

怎么会这样?我不明白为什么首先要对数据进行反序列化,但是如何在SortInfo不设置属性的情况下创建对象就更加神秘了。

在文件中是必要的过程Symfony 2.8Util.SortInfo.yml删除此文件会导致异常:

Symfony\Component\HttpKernel\Exception\BadRequestHttpException:“您必须为 AppBundle\Util\SortInfo::$sortBy 定义一个类型。”

/.../vendor/friendsofsymfony/rest-bundle/Request/RequestBodyParamConverter.php

在这里,我不明白为什么SortInfo::$sortBy是一个问题,而不是SortInfo它自己。此外,删除文件Symfony 3.4不会改变任何内容。

但至少此错误消息确认 FOSRequestBodyParamConverter参与了该过程。

按照Symfony 文档,应该有必要手动指定应该转换的参数(尽管在没有这个配置的情况下它工作得很好Symfony 2.8):

/**
 * @FOSRest\View()
 * @ParamConverter("sortInfo", converter="fos_rest.request_body")
 */
public function sortAction(SortInfo $sortInfo) {
    ...
}

但是,添加此配置会导致另一个错误Symfony 3.4

未捕获的 PHP 异常 RuntimeException:“转换器 'fos_rest.request_body' 不支持参数 '$sortInfo' 的转换

底线:

标签: phpsymfonyfosrestbundlejmsserializerbundle

解决方案


推荐阅读