Writing by Peter Hilton

Browsing a JSON API in HTML

Rendering JSON responses as HTML with links and annotations 2023-01-17 #API #documentation

Marco Kaufmann

  1. Explanation order
  2. Backwards API docs
  3. Annotation styles
  4. API docs annotations
  5. Annotations in HTML
  6. JSON API responses in HTML ←
  7. Generated API examples

API documentation annotations in HTML showed how to document an HTTP API by example, to create more usable documentation. An API’s implementation could take this idea further by integrating these annotations into the API itself.

HTML representations as live documentation

Consider using a Pirate API to build a retirement planning SaaS for scurvy sons of dogs (transcript) who sail the high seas. The API’s ship’s crew HTTP resource provides the following JSON response.

GET /ship/ShpOWZxvR3mxMndyC2aJ3A/crew HTTP/1.1
Accept: application/json
Content-Type: application/vnd.restful+json

[
  {
    "url": "/pirate/CecWcS52T4ePtOVd0L5EyQ",
    "name": "Alexander Smollett",
    "rank": "Captain"
  },
  {
    "url": "/pirate/zp9UrJznRliWESfom9ScRA",
    "name": "Job Anderson",
    "rank": "Boatswain"
  },
  {
    "url": "/pirate/EYV3NOklSWibT95TsVyABA",
    "name": "Long John Silver",
    "rank": "Cook"
  }
]

In practice, the response will not format its JSON body, making it harder to debug:

[{"url":"/pirate/CecWcS52T4ePtOVd0L5EyQ","name":"Alexander Smollett","rank":"Captain"
},{"url":"/pirate/zp9UrJznRliWESfom9ScRA","name":"Job Anderson","rank":"Boatswain"},{
"url":"/pirate/EYV3NOklSWibT95TsVyABA","name":"Long John Silver","rank":"Cook"}]

While plenty of tools will format this JSON response for you, you could also build it into the API, so that requesting the same resource URL in a web browser outputs a formatted JSON response:

[
  {
    "url": "/pirate/CecWcS52T4ePtOVd0L5EyQ",
    "name": "Alexander Smollett",
    "rank": "Captain"
  },
  {
    "url": "/pirate/zp9UrJznRliWESfom9ScRA",
    "name": "Job Anderson",
    "rank": "Boatswain"
  },
  {
    "url": "/pirate/EYV3NOklSWibT95TsVyABA",
    "name": "Long John Silver",
    "rank": "Cook"
  }
]

You can do this with content negotiation, by serving an HTML response for requests with an Accept: text/html header, which web browsers send, instead of Accept: application/json (simplifying a little). Now, instead of static documentation that shows a fixed set of request-response examples, client developers have the option to render every response as HTML.

Browsing a hypermedia API

Once you can view API responses in a web browser, you could add a hyperlink to the HTTP resource for each pirate crew member.

[
  {
    "url": "/pirate/CecWcS52T4ePtOVd0L5EyQ",
    "name": "Alexander Smollett",
    "rank": "Captain"
  },
  {
    "url": "/pirate/zp9UrJznRliWESfom9ScRA",
    "name": "Job Anderson",
    "rank": "Boatswain"
  },
  {
    "url": "/pirate/EYV3NOklSWibT95TsVyABA",
    "name": "Long John Silver",
    "rank": "Cook"
  }
]

The API’s HTML rendering could automatically render these links because in the example above, the RESTful JSON response body uses url properties to link to other HTTP resources. However, RESTful JSON would only make it possible to link HTTP GET requests; a more complex API requires a richer hypermedia language, such as Hypertext Application Language (HAL).

Evert Pot’s Curveball Browser implements exactly this for a HAL API. Curveball provides a far more sophisticated HTML rendering than the example above. As well as rendering JSON responses as formatted HTML, with hyperlinks between resources, the response also renders forms for templated URLs, and multiple output formats. This makes it much easier to explore and understand an HTTP API, and neatly demonstrates the value of hypermedia in an actually-REST API.

For a real-world example, NRK’s (Norwegian television) TV series colour palette API renders this HTML preview of the series Lykkeland’s actual colour palette in the browser:

Preview of the HTML representation of a TV series’ colour palette

To use the API programmatically, use the correct Accept header:

GET /tv/series/lykkeland HTTP/1.1
Accept: application/vnd.nrk.fargerik.palette.2.0+json
Host: fargerik-psapi.nrk.no

This fetches the following JSON response:

HTTP/1.1 200 OK
Content-Type: application/vnd.nrk.fargerik.palette.2.0+json; charset=utf-8

{
    "dark": "#1a3737",
    "disabledOnDark": "#8c9e9e",
    "disabledOnMedium": "#bdcccd",
    "light": "#affdff",
    "medium": "#305253",
    "mediumDark40": "#274748",
    "mediumLight10": "#3d6364",
    "mediumLight20": "#497475",
    "mediumLight5": "#365b5c",
    "whiteDark30": "#bac3c3",
    "whiteMedium30": "#c1cbcb"
}

The HTML preview saves you the trouble of trying to visualise RGB colours in your head, and checks for accessible contrast. However, it doesn’t tell you what the properties mediumDark40 and whiteDark30 mean. Documentation annotations could help there.

Annotating HTML representations

Given an HTML rendering of a JSON response, we can also add annotations to document the API, in addition to making it browsable. In the following example, hover a highlighted name property name to show its annotation:

[
  {
    "url": "/pirate/CecWcS52T4ePtOVd0L5EyQ",
    "name": "Alexander Smollett",
    "rank": "Captain"
  },
  {
    "url": "/pirate/zp9UrJznRliWESfom9ScRA",
    "name": "Job Anderson",
    "rank": "Boatswain"
  },
  {
    "url": "/pirate/EYV3NOklSWibT95TsVyABA",
    "name": "Long John Silver",
    "rank": "Cook"
  }
]

This example uses HTML abbr elements, which avoid cluttering the page but require a hover interaction that makes them harder to browse. A better layout would render API documentation annotations in HTML. This would require a detailed model of the API, so that the HTML renderer knows where to highlight the response, and which annotation to render.

Annotated examples improve API documentation, and APIs could integrate their own documentation. Meanwhile, most HTTP APIs don’t even scratch the surface of good developer experience.

Share on TwitterShare on LinkedIn