从Symfony2控制器返回基于“Accept:application / json”的JSON

时间:2013-05-22 23:06:20

标签: json symfony symfony-2.2

我有一个通过SensioGeneratorBundle生成的CRUD表单,described here。这很有效。

但是,如果“Accept”HTTP标头仅包含“application / json”,我还想返回JSON而不是HTML响应。我正在研究JSON服务的原型,这将帮助我快速启动。

我发现我可以将我的实体变成这样的JSON字符串:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new 
JsonEncoder()));
$json = $serializer->serialize($entity, 'json');

但是,最后,$ json包含一个字符串,它是我的JSON数据。我想直接将它输出到请求者,而不是渲染通常的视图。我已经尝试返回一个新的JsonResponse($ json),但它重新编码了JSON字符串,因此它最终会被双重编码。

所以我有两个问题:

  1. 检查HTTP请求标头的“正确”方法是什么?我知道我可以查看$ _SERVER,但我认为在Symfony2中可能有更好的方法。
  2. 返回JSON字符串或将我的实体转换为直接返回给请求者的JSON的“正确”方法是什么,而不呈现通常的视图。
  3. 谢谢!

1 个答案:

答案 0 :(得分:0)

这将验证当前请求是否为XHR,然后发回正确格式化的JSON数据:

public function someAction(Request $request)
{
    if ($request->isXmlHttpRequest()) {
        $serializer = new Serializer(array(
            new GetSetMethodNormalizer()
        ), array(
            'json' => new JsonEncoder()
        ));

        $response = $serializer->serialize(array(
            'success' => true,
            'data' => array(
                'entity' => $entities,
            )
        ), 'json');

        return new Response($response, 200, array('Content-Type' => 'application/json'));
    } else {
        // Run "normal" request code, render a view
    }
}

顺便说一句,JMSSerializerBundle使序列化语法更直接(因为,让我们面对它,本机Symfony的方式很难看)并且还提供了一些额外的功能,例如排除实体字段以序列化(通过注释)。

使用JMS,我的代码如下所示:

if ($request->isXmlHttpRequest()) {
    $response = array('success' => true, 'data' => array(
        'entity' => $this->container->get('serializer')->serialize($entity, 'json'),
        'lastPage' => $lastPage,
    ));
    return new Response(json_encode($response), 200, array('Content-Type' => 'application/json'));
}

最后,“成功”和“数据”绝不是必需的,它只是我用来分割状态和数据以便在JavaScript中可读的结构。