Pragmatism in the real world

Render an array based on accept header

I’m currently working on an API using Slim 3 and needed a generic way to render arrays to XML, JSON or HTML based on the Request’s Accept header.

This is just good practice. The Accept header is used by a client to specify the media types that it accepts. Therefore if our client would like XML, I’d like to give it XML. Similarly for JSON. I also like to support an HTML rendering on my API if I can as it makes exploration much easier.

This seemed like an ideal thing for a component and so I wrote rka-content-type-renderer! (One day I’ll work out how to name things, but for now, if it starts with rka, then it’s probably a reusable component!)

It’s PSR-7 compliant because if you’re going to write something that deals with HTTP nowadays, PSR-7 is the only sensible interface to target. Therefore, this component renders to a PSR-7’s Response object’s body.

Usage is really simple:

$data = [
    'items' => [
        [
            'name' => 'Alex',
            'is_admin' => true,
        ],
        [
            'name' => 'Robin',
            'is_admin' => false,
            'link' => 'http://example.com',
        ],
    ],
];
$renderer = new \RKA\ContentTypeRenderer\Renderer();
$response  = $renderer->render($request, $response, $data);
return $response->withStatus(200);

The $request and $response objects must implement PSR-7’s RequestInterface and ResponseInterface respectively. This makes it very easy to use within say Radar, Expressive, Slim or any other system that can bridge to PSR-7.

In this case, the output for JSON is:

{
    "items": [
        {
            "name": "Alex",
            "is_admin": true
        },
        {
            "name": "Robin",
            "is_admin": false,
            "link": "http:\/\/example.com"
        }
    ]
}

& for XML:

<?xml version="1.0"?>
<root>
  <items>
    <name>Alex</name>
    <is_admin>1</is_admin>
  </items>
  <items>
    <name>Robin</name>
    <is_admin>0</is_admin>
    <link>http://example.com</link>
  </items>
</root>

Finally, it will also render the array as an HTML unsigned list if the content-type is text/html which makes examining an API using a web browser very easy and worth doing:


Obviously, in the HTML, we link any links so that the user can explore the API data, simply by clicking.

Hal support

While doing this, I also added support for rendering Nocarrier/Hal objects too as the HAL specification supports both JSON and XML, so it seems logical to send the correct format back to the client based on what they’ve asked for.

All in all, I’ve found this to be a useful component and if you have a similar need, then maybe this will help.

7 thoughts on “Render an array based on accept header

  1. Hey Rob,

    Thank you. You did a great job.

    But I think you find something missing in the PSR-7? We need some way to have a Stream which can be used by any psr-7 implementations. What do you think about it?

    1. Hari,

      Could you expand what you mean? rka-content-type-renderer will use the stream attached to the supplied response unless it can't, in which case it uses a simple one.

Comments are closed.