0

I've got a CRUD form generated via the SensioGeneratorBundle, as described here. This works great.

However, I would like to also return JSON, rather than HTML responses, if the "Accept" HTTP header contains only "application/json". I'm working on a prototype for a JSON service and this would help me jump start things.

I figured out that I can turn my entities into a JSON string like this:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new 
JsonEncoder()));
$json = $serializer->serialize($entity, 'json');

However, at the end of that, $json contains a string that is my JSON data. I want to just directly output that to the requestor, rather than render the usual view. I've tried returning a new JsonResponse($json), but it re-encodes the JSON string, so it winds up double-encoded.

So I have two questions:

  1. What is the "correct" way to inspect the HTTP requestion headers? I know I can just look in $_SERVER, but I'm thinking that there may be a better way to do this in Symfony2.
  2. What is the "correct" way to return a JSON string, or to translate my entities into JSON that is returned straight to the requestor, without rendering the usual view.

Thanks!

1 Answer 1

0

This will verify if the current request is XHR and then send back properly formatted JSON data:

public function someAction(Request $request)
{
    if ($request->isXmlHttpRequest()) {
        $serializer = new Serializer(array(
            new GetSetMethodNormalizer()
        ), array(
            'json' => new JsonEncoder()
        ));

        $response = $serializer->serialize(array(
            'success' => true,
            'data' => array(
                'entity' => $entities,
            )
        ), 'json');

        return new Response($response, 200, array('Content-Type' => 'application/json'));
    } else {
        // Run "normal" request code, render a view
    }
}

By the way, JMSSerializerBundle makes the serializing syntax more straightforward (because, let's face it, the native Symfony way for this is ugly) and also provides some additionnal features such as excluding entity fields to serialize (through annotations).

With JMS, my code looks like this:

if ($request->isXmlHttpRequest()) {
    $response = array('success' => true, 'data' => array(
        'entity' => $this->container->get('serializer')->serialize($entity, 'json'),
        'lastPage' => $lastPage,
    ));
    return new Response(json_encode($response), 200, array('Content-Type' => 'application/json'));
}

And finally, 'success' and 'data' are in no way required, it's just the structure I use to split status and data to be readable in JavaScript.

3
  • That's great! I did have to modify it slightly because the entities were still being double-encoded. Here's what I came up with: $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); $response = $serializer->serialize(array('success' => true, 'data' => array('entity' => $entities, )), 'json'); $result = new Response($response, 200, array('Content-Type' => 'application/json'));
    – Josh
    Commented May 23, 2013 at 0:58
  • Ok, so I can't figure out how to get a line break in comments. You'll need to reformat the code in my previous comment... sorry. Also, I had to change $request to $this->getRequest().
    – Josh
    Commented May 23, 2013 at 1:02
  • Oops sorry, I took that snippet from my code and I'm doing the encoding slightly differently from you. Comment only support code tags, nothing else ;) I'll $request works, I'll edit the answer Commented May 23, 2013 at 1:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.