Wie kann ich eine JSON-Antwort in symfony2 controller senden?

90

Ich verwende jQuery, um mein eingebautes Formular zu bearbeiten Symfony.

Ich zeige das Formular im jQueryDialog und sende es dann ab.

Die Daten werden korrekt in die Datenbank eingegeben.

Aber ich weiß nicht, ob ich etwas JSONzurückschicken muss jQuery. Eigentlich bin ich etwas verwirrt JSON.

Angenommen, ich habe meiner Tabelle mit `` jQuery eine Zeile hinzugefügt. Wenn ich das Formular sende, möchte ich diese Zeilendaten nach dem Senden der Daten zurücksenden, damit ich die Tabellenzeile dynamisch hinzufügen kann, um die hinzugefügten Daten anzuzeigen.

Ich bin verwirrt, wie ich diese Daten zurückbekommen kann.

Dies ist mein aktueller Code:

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

Dies ist nur die Vorlage mit der Erfolgsmeldung.

Fata Morgana
quelle

Antworten:

187

Symfony 2.1

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

return $response;

Symfony 2.2 und höher

Sie haben eine spezielle JsonResponse- Klasse, die das Array in JSON serialisiert:

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

Wenn Ihr Problem jedoch darin besteht, wie eine Entität serialisiert wird, sollten Sie sich JMSSerializerBundle ansehen

Angenommen, Sie haben es installiert, müssen Sie es einfach tun

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

return new Response($serializedEntity);

Sie sollten auch in StackOverflow nach ähnlichen Problemen suchen:

Vitalii Zurian
quelle
1
Wie serialisieren wir die Entität UND senden sie als JSON-Antwort? Ich habe seit einer Woche danach gesucht
George Katsanos
Sie können auch symfony JsonResponse (Symfony \ Component \ HttpFoundation \ JsonResponse)
Kiddo
5
Es ist besser, den Header für den Inhaltstyp so festzulegen, dass eine neue Antwort zurückgegeben wird ($ serializedEntity, 200, array ('Content-Type' => 'application / json')).
Sergii Smirnov
Sergiis Vorschlag ist der beste (zumindest für mich). Wenn ich den Inhaltstyp nicht einstelle, erhalte ich auf dem Client einen Text- / HTML-Inhaltstyp. Wenn ich JsonResponse benutze, bekomme ich aus irgendeinem seltsamen Grund eine einzelne Zeichenfolge mit dem Inhalt darin
LuisF
56

Symfony 2.1 verfügt über eine JsonResponse- Klasse.

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

Das übergebene Array wird JSON-codiert, der Statuscode wird standardmäßig auf 200 gesetzt und der Inhaltstyp wird auf application / json festgelegt.

Es gibt auch eine praktische setCallbackFunktion für JSONP.

jmaloney
quelle
16

Seit Symfony 3.1 können Sie JSON Helper http://symfony.com/doc/current/book/controller.html#json-helper verwenden

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
quelle
10

Um die Antwort von @thecatontheflat zu vervollständigen, würde ich empfehlen, Ihre Aktion auch in einen try … catchBlock zu packen . Dadurch wird verhindert, dass Ihr JSON-Endpunkt bei Ausnahmen beschädigt wird. Hier ist das Skelett, das ich benutze:

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

    }
}

Auf diese Weise verhält sich Ihr Endpunkt auch bei Fehlern konsistent und Sie können sie direkt auf Client-Seite behandeln.

Slava Fomin II
quelle
8

Wenn Ihre Daten bereits serialisiert sind:

a) Senden Sie eine JSON-Antwort

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

b) Senden Sie eine JSONP-Antwort (mit Rückruf)

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

Wenn Ihre Daten serialisiert werden müssen:

c) Senden Sie eine JSON-Antwort

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

d) Senden einer JSONP-Antwort (mit Rückruf)

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

e) Verwenden Sie Gruppen in Symfony 3.xx

Erstellen Sie Gruppen in Ihren Entitäten

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

    // ...
}

Normalisieren Sie Ihr Doctrine-Objekt innerhalb der Logik Ihrer Anwendung

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