symfony2 컨트롤러에서 JSON 응답을 보내는 방법


90

jQuery내장 된 양식을 편집 하는 데 사용 하고 Symfony있습니다.

jQuery대화 상자에 양식을 표시 한 다음 제출합니다.

데이터가 데이터베이스에 올바르게 입력되고 있습니다.

하지만 일부를으로 JSON다시 보내야하는지 여부는 모르겠습니다 jQuery. 사실 나는 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');               
}

이것은 성공 메시지가있는 템플릿입니다.

답변:


187

심포니 2.1

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

return $response;

Symfony 2.2 이상

배열을 JSON으로 직렬화하는 특수 JsonResponse 클래스 가 있습니다 .

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/…
George Katsanos

또한 심포니 JsonResponse (심포니 \ 구성 요소 \ HttpFoundation \ JsonResponse)를 사용할 수 있습니다
얘야

5
콘텐츠 유형 헤더를 설정하는 것이 좋습니다. return new 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;
    }

    // ...
}

응용 프로그램의 논리 내에서 Doctrine Object를 정규화합니다.

<?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;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.