Como posso enviar resposta JSON no controlador symfony2

90

Estou usando jQuerypara editar meu formulário que está embutido Symfony.

Estou mostrando o formulário na jQuerycaixa de diálogo e enviando-o.

Os dados estão entrando corretamente no banco de dados.

Mas não sei se preciso mandar alguns de JSONvolta para jQuery. Na verdade, estou um pouco confuso com as JSONcoisas.

Suponha que eu tenha adicionado uma linha em minha tabela com `` jQuery e quando eu enviar o formulário, depois que os dados forem enviados, eu queira enviar de volta esses dados de linha para que possa adicionar dinamicamente a linha da tabela para mostrar os dados adicionados.

Estou confuso como posso obter esses dados de volta.

Este é meu código atual:

$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');               
}

Este é apenas o modelo com mensagem de sucesso.

Miragem
fonte

Respostas:

187

Symfony 2.1

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

return $response;

Symfony 2.2 e superior

Você tem uma classe especial JsonResponse , que serializa a matriz para JSON:

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

Mas se o seu problema é como serializar entidade, então você deve dar uma olhada em JMSSerializerBundle

Supondo que você o tenha instalado, você simplesmente terá que fazer

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

return new Response($serializedEntity);

Você também deve verificar se há problemas semelhantes no StackOverflow:

Vitalii Zurian
fonte
1
Então, como serializamos a entidade E a enviamos como uma resposta JSON? Estive procurando por isso por uma semana .. stackoverflow.com/questions/14798532/…
George Katsanos
Você também pode usar o symfony JsonResponse (Symfony \ Component \ HttpFoundation \ JsonResponse)
Kiddo
5
É melhor definir o retorno do cabeçalho do tipo de conteúdo como nova Resposta ($ serializedEntity, 200, array ('Content-Type' => 'application / json'));
Sergii Smirnov
A sugestão do Sergii é a melhor (pelo menos para mim), se eu não definir o Content-Type, no cliente receberei um content-type text / html. Se eu usar o JsonResponse, por algum motivo estranho, recebo uma única string com o conteúdo dentro
LuisF
56

Symfony 2.1 tem uma classe JsonResponse .

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

O array passado será codificado em JSON, o código de status será padronizado como 200 e o tipo de conteúdo será definido como application / json.

Também existe uma setCallbackfunção útil para JSONP.

Jmaloney
fonte
16

Desde Symfony 3.1 você pode usar 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());
}
Bettinz
fonte
10

Para completar @thecat na resposta plana, recomendo também envolver sua ação dentro de um try … catchbloco. Isso impedirá que seu endpoint JSON interrompa as exceções. Aqui está o esqueleto que uso:

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(),
        ]);

    }
}

Desta forma, seu endpoint se comportará de maneira consistente mesmo em caso de erros e você poderá tratá-los diretamente do lado do cliente.

Slava Fomin II
fonte
8

Se seus dados já estiverem serializados:

a) enviar uma resposta 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) enviar uma resposta JSONP (com callback)

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;
}

Se seus dados precisam ser serializados:

c) enviar uma resposta JSON

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

d) enviar uma resposta JSONP (com callback)

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

e) usar grupos no Symfony 3.xx

Crie grupos dentro de suas entidades

<?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;
    }

    // ...
}

Normalize seu objeto Doctrine dentro da lógica de sua aplicação

<?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;
Avram Cosmin
fonte