¿Cómo puedo enviar una respuesta JSON en el controlador Symfony2?

90

Estoy usando jQuerypara editar mi formulario que está integrado Symfony.

Estoy mostrando el formulario en el jQuerycuadro de diálogo y luego lo envío.

Los datos se ingresan correctamente en la base de datos.

Pero no sé si necesito enviar algunos de JSONvuelta jQuery. En realidad, estoy un poco confundido JSON.

Supongamos que agregué una fila en mi tabla con `` jQuery y cuando envío el formulario, luego de enviar los datos, quiero enviar esos datos de la fila para poder agregar dinámicamente la fila de la tabla para mostrar los datos agregados.

Estoy confundido de cómo puedo recuperar esos datos.

Este es mi código actual:

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

Esta es solo la plantilla con mensaje de éxito.

Espejismo
fuente

Respuestas:

187

Symfony 2.1

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

return $response;

Symfony 2.2 y superior

Tiene una clase especial JsonResponse , que serializa la matriz en JSON:

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

Pero si su problema es Cómo serializar la entidad , debería echar un vistazo a JMSSerializerBundle

Suponiendo que lo tenga instalado, simplemente tendrá que hacer

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

return new Response($serializedEntity);

También debe verificar si hay problemas similares en StackOverflow:

Vitalii Zurian
fuente
1
Entonces, ¿cómo serializamos la entidad y la enviamos como una respuesta JSON? Lo he estado buscando durante una semana .. stackoverflow.com/questions/14798532/…
George Katsanos
También puedes usar Symfony JsonResponse (Symfony \ Component \ HttpFoundation \ JsonResponse)
Kiddo
5
Es mejor configurar el encabezado del tipo de contenido para devolver una nueva respuesta ($ serializedEntity, 200, array ('Content-Type' => 'application / json'));
Sergii Smirnov
La sugerencia de Sergii es la mejor (al menos para mí), si no configuro el Tipo de contenido, en el cliente recibiré un tipo de contenido de texto / html. Si uso JsonResponse, por alguna extraña razón, obtengo una sola cadena con el contenido adentro
LuisF
56

Symfony 2.1 tiene una clase JsonResponse .

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

La matriz pasada estará codificada en JSON, el código de estado predeterminado será 200 y el tipo de contenido se establecerá en application / json.

También hay una setCallbackfunción útil para JSONP.

jmaloney
fuente
16

Desde Symfony 3.1 puedes 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
fuente
10

Para completar la respuesta de @thecatontheflat, recomendaría también envolver su acción dentro de un try … catchbloque. Esto evitará que su punto final JSON se rompa en las excepciones. Aquí está el 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(),
        ]);

    }
}

De esta manera, su punto final se comportará de manera uniforme incluso en caso de errores y podrá tratarlos directamente en el lado del cliente.

Slava Fomin II
fuente
8

Si sus datos ya están serializados:

a) envía una respuesta 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 una respuesta JSONP (con devolución de llamada)

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

Si sus datos deben serializarse:

c) enviar una respuesta JSON

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

d) enviar una respuesta JSONP (con devolución de llamada)

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

e) usar grupos en Symfony 3.xx

Crea grupos dentro de tus 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;
    }

    // ...
}

Normaliza tu Objeto Doctrine dentro de la lógica de tu aplicación

<?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
fuente