Pragmatism in the real world

Returning JSON using the Accept header in ZF2

2 December 2012: Note that as of ZF2.0.4, this no longer works due to changes to fix a security issue. See the release notes for further information.

Following yesterday’s article on returning JSON from a ZF2 controller action, Lukas suggested that I should also demonstrate how to use the Accept header to get JSON. So this is how you do it!

Set up the JsonStrategy

We set up the JsonStrategy as we did in returning JSON from a ZF2 controller action.

Return a ViewModel from the controller

As we’re letting the JsonStrategy intercede for us, we don’t need to do anything special in our controller at all. In this case, we simply return a normal ViewModel for use by either the JsonRenderer or PhpRenderer as required:

module/Application/src/Application/Controller/IndexController.php:

namespace ApplicationController;

use ZendMvcControllerActionController,
    ZendViewModelViewModel;

class IndexController extends ActionController
{
    public function anotherAction()
    {
        $matches[] = array('distance' => 10, 'playground' => array('a'=>1));
        $matches[] = array('distance' => 20, 'playground' => array('a'=>2));
        $matches[] = array('distance' => 30, 'playground' => array('a'=>3));

        $result = new ViewModel(array(
            'success'=>true,
            'results' => $matches,
        ));
        return $result;
    }
}

with our HTML view script:

module/Application/view/index/another.phtml:

< ?php if ($success): ?>

Results

    < ?php foreach ($results as $row): ?>
  • Distance: < ?php echo $this->escape($row['distance']);?>m
  • < ?php endforeach; ?>
< ?php endif; ?>

So if you set up a route and browse to it, you’ll see a nicely rendered page.

Retrieving the data as JSON

To retrieve the data via JSON, we need a client where we can set the Accept header. We’ll use curl for this test. When doing anything with APIs and testing, we head over to LornaJane‘s blog for the Curl Cheat Sheet and use this command line:

curl -H "Accept: application/json" http://zf2test.dev/json/another

and you should see the output of:

{
  "content":{
    "success":true,
    "results": [
      {"distance":10,"playground":{"a":1}},
      {"distance":20,"playground":{"a":2}},
      {"distance":30,"playground":{"a":3}}
    ]
  }
}

(Formatted for readability – you get the result back on a single line from curl.)

This way you can use the same controllers for your HTML views and for returning JSON to those clients that can use it.