如何在symfony2控制器中发送JSON响应


90

我正在jQuery编辑内置的表单Symfony

我在jQuery对话框中显示表单,然后提交。

数据已正确输入数据库。

但是我不知道是否需要发一些JSONjQuery。其实我对JSON事情有点困惑。

假设我在表中添加了``jQuery,并且当我提交表单时,然后在提交数据之后,我想发回那些行数据,以便我可以动态添加表行以显示添加的数据。

我很困惑如何获取这些数据。

这是我当前的代码:

$editForm = $this->createForm(new StepsType(), $entity);

$request = $this->getRequest();

$editForm->bindRequest($request);

if ($editForm->isValid()) {
    $em->persist($entity);
    $em->flush();

    return $this->render('::success.html.twig');               
}

这只是带有成功消息的模板。

Answers:


187

Symfony 2.1

$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');

return $response;

Symfony 2.2及更高版本

您具有特殊的JsonResponse类,该类将数组序列化为JSON:

return new JsonResponse(array('name' => $name));

但是,如果您的问题是如何序列化实体,那么您应该看看JMSSerializerBundle

假设您已安装它,只需要做

$serializedEntity = $this->container->get('serializer')->serialize($entity, 'json');

return new Response($serializedEntity);

您还应该检查StackOverflow上是否存在类似问题:


1
那么,我们如何序列化实体并将其作为JSON响应发送呢?我一直在寻找这一个星期.. stackoverflow.com/questions/14798532/...
乔治Katsanos

您还可以使用symfony JsonResponse(Symfony \ Component \ HttpFoundation \ JsonResponse)
Kiddo

5
最好将内容类型标头设置为返回新的Response($ serializedEntity,200,array('Content-Type'=>'application / json'));
Sergii Smirnov

Sergii的建议是最好的(至少对我而言),如果我未设置Content-Type,则在客户端上,我将收到text / html content-type。如果我使用JsonResponse,出于某种奇怪的原因,我会得到一个包含内容的字符串
LuisF

56

Symfony 2.1具有JsonResponse类。

return new JsonResponse(array('name' => $name));

传入的数组将使用JSON编码,状态码将默认为200,内容类型将设置为application / json。

setCallbackJSONP 还有一个方便的功能。


16

从Symfony 3.1开始,您可以使用JSON Helper http://symfony.com/doc/current/book/controller.html#json-helper

public function indexAction()
{
// returns '{"username":"jane.doe"}' and sets the proper Content-Type header
return $this->json(array('username' => 'jane.doe'));

// the shortcut defines three optional arguments
// return $this->json($data, $status = 200, $headers = array(), $context = array());
}

10

为了完成@thecatontheflat答案,我建议您也将动作包装在一个try … catch块内。这将防止您的JSON端点发生异常。这是我使用的骨架:

public function someAction()
{
    try {

        // Your logic here...

        return new JsonResponse([
            'success' => true,
            'data'    => [] // Your data here
        ]);

    } catch (\Exception $exception) {

        return new JsonResponse([
            'success' => false,
            'code'    => $exception->getCode(),
            'message' => $exception->getMessage(),
        ]);

    }
}

这样,即使出现错误,您的端点也将始终如一地运行,并且您将能够在客户端正确对待它们。


8

如果您的数据已经序列化:

a)发送一个JSON响应

public function someAction()
{
    $response = new Response();
    $response->setContent(file_get_contents('path/to/file'));
    $response->headers->set('Content-Type', 'application/json');
    return $response;
}

b)发送JSONP响应(带有回调)

public function someAction()
{
    $response = new Response();
    $response->setContent('/**/FUNCTION_CALLBACK_NAME(' . file_get_contents('path/to/file') . ');');
    $response->headers->set('Content-Type', 'text/javascript');
    return $response;
}

如果您的数据需要序列化:

c)发送一个JSON响应

public function someAction()
{
    $response = new JsonResponse();
    $response->setData([some array]);
    return $response;
}

d)发送JSONP响应(带有回调)

public function someAction()
{
    $response = new JsonResponse();
    $response->setData([some array]);
    $response->setCallback('FUNCTION_CALLBACK_NAME');
    return $response;
}

e)在Symfony 3.xx中使用组

在实体内创建组

<?php

namespace Mindlahus;

use Symfony\Component\Serializer\Annotation\Groups;

/**
 * Some Super Class Name
 *
 * @ORM    able("table_name")
 * @ORM\Entity(repositoryClass="SomeSuperClassNameRepository")
 * @UniqueEntity(
 *  fields={"foo", "boo"},
 *  ignoreNull=false
 * )
 */
class SomeSuperClassName
{
    /**
     * @Groups({"group1", "group2"})
     */
    public $foo;
    /**
     * @Groups({"group1"})
     */
    public $date;

    /**
     * @Groups({"group3"})
     */
    public function getBar() // is* methods are also supported
    {
        return $this->bar;
    }

    // ...
}

在应用程序逻辑中规范您的教义对象

<?php

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
// For annotations
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

...

$repository = $this->getDoctrine()->getRepository('Mindlahus:SomeSuperClassName');
$SomeSuperObject = $repository->findOneById($id);

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer($classMetadataFactory);
$callback = function ($dateTime) {
    return $dateTime instanceof \DateTime
        ? $dateTime->format('m-d-Y')
        : '';
};
$normalizer->setCallbacks(array('date' => $callback));
$serializer = new Serializer(array($normalizer), array($encoder));
$data = $serializer->normalize($SomeSuperObject, null, array('groups' => array('group1')));

$response = new Response();
$response->setContent($serializer->serialize($data, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.