The Pretty JSON Revolution

peter@ohler.com

Author: Peter Ohler Published: February 22, 2021

Wouldn't it be nice if more JSON tools supported a truly pretty JSON format? Demand options for truly pretty JSON now! Viva la revolucion!

If only it were that easy. JSON format has become wildly popular over the last decade easily passing XML as the format of choice. For us humans JSON is much easier to read than XML if the JSON is properly formatted. Sadly most tools for viewing or formating JSON seem to be stuck on one of two formats. One format is the single line format and the other is a simple expanded format. There are other options though with some tools.

One tool that offers more options is the oj application which is part of the golang OjG package. The oj application will be used to illustrate the range of JSON formats from the ugly up to the beauty of pretty JSON. Follow along and try out your favorite JSON sample on each step.

One Line

The tight one line JSON format is used when trying to minimize the size of a JSON document. It is the preferred format for transmitting and storing JSON as it takes less bandwidth and less disk space. For viewing, it is hard for the eye to find elements of interests and difficult to determine element boundaries. It has to be the ugliest of all JSON formats.

$ oj -i 0 colors.json
{"colors":[{"color":"black","hex":"#000","rgb":[0,0,0]},{"color"
:"red","hex":"#f00","rgb":[255,0,0]},{"color":"yellow","hex":"#f
f0","rgb":[255,255,0]},{"color":"green","hex":"#0f0","rgb":[0,25
5,0]},{"color":"cyan","hex":"#0ff","rgb":[0,255,255]},{"color":"
blue","hex":"#00f","rgb":[0,0,255]},{"color":"magenta","hex":"#f
0f","rgb":[255,0,255]},{"color":"white","hex":"#fff","rgb":[255,
255,255]}]}

One Line Per Node

What many packages refer to as pretty is an expanded format where every element and each array and object start are on separate lines. The core golang json.MarshalIndent() function produces an example of this format. The format takes up so much vertical space the example on the right had to be cut off to avoid filling up this article with just large amounts of white space.

With the expanded (pretty?) format it is certainly easier to determine element boundaries but you need a large screen or to be good at scrolling to find what you are looking for. So the expanded format is a step up from the one line format which makes it a bit prettier but it is a weak effort that is not without flaws.

$ oj -i 2 colors.json
{
  "colors": [
    {
      "color": "black",
      "hex": "#000",
      "rgb": [
        0,
        0,
        0
      ]
    },
    {
      "hex": "#f00",
      "rgb": [
        255,
        0,
        0
      ],
      "color": "red"
    },
...

Sorted Object Keys

In many implementations JSON objects, whether implemented as a golang map, Ruby Hash, Python dict, or what ever your language of choice uses, the order of object elements is random. That makes it more difficult to visually scan a set of elements and pick out the same keyed element in each JSON object. The brain is good at picking out visual or spacial patterns but if the layout changes each each time there is no pattern to pickup on. A visual scan has to be done, looking at each key until the target is identified. JSON can be made prettier by sorting the JSON object members by element keys.

A sorted expanded format is a step up from just the expanded format but it still suffers from taking up lot of vertical space. If someone was writing the JSON by hand they would probably not elect to expand the JSON to quite the level that most packages or libraries do.

$ oj -i 2 -s colors.json
{
  "colors": [
    {
      "color": "black",
      "hex": "#000",
      "rgb": [
        0,
        0,
        0
      ]
    },
    {
      "color": "red",
      "hex": "#f00",
      "rgb": [
        255,
        0,
        0
      ]
    },
...

Human Style

The ideal pretty JSON pretty is to have the format look like a human had typed it in. Well a pedantic human that didn't make mistakes. Just like Goldilocks, the optimum middle ground between a single line and a fully expanded format is the goal. The algorithm oj uses considers a suggested edge to not exceed and a maximum element depth allowed on a single line. Those two parameters are specified as a float where the whole number part is the edge and the fractional part or the number of 10ths is the maximum depth on a single line. With those two parameters a reasonable human style format can be achieved and the results are looking rather pretty.

$ oj -p 80.3 colors.json
{
  "colors": [
    {"color": "black", "hex": "#000", "rgb": [0, 0, 0]},
    {"color": "red", "hex": "#f00", "rgb": [255, 0, 0]},
    {"color": "yellow", "hex": "#ff0", "rgb": [255, 255, 0]},
    {"color": "green", "hex": "#0f0", "rgb": [0, 255, 0]},
    {"color": "cyan", "hex": "#0ff", "rgb": [0, 255, 255]},
    {"color": "blue", "hex": "#00f", "rgb": [0, 0, 255]},
    {"color": "magenta", "hex": "#f0f", "rgb": [255, 0, 255]},
    {"color": "white", "hex": "#fff", "rgb": [255, 255, 255]}
  ]
}

Human Style with Colors

With the human style formatting the JSON sample is very readable but it can be made prettier. Well at least for those of us than see in color. With the -c option or the -b option the formatted JSON now has colors. While colors do make the output prettier they also make it easier for the eye to discern keys, string, boolean, and numbers more easily. Try it, look at the non-colored JSON and the colored and pick out your preferred color name. Maybe not nirvana but compared to the first, one line format, the colored pretty output is a completely different level.

$ oj -p 80.3 -c colors.json
{
  "colors": [
    {"color": "black", "hex": "#000", "rgb": [0, 0, 0]},
    {"color": "red", "hex": "#f00", "rgb": [255, 0, 0]},
    {"color": "yellow", "hex": "#ff0", "rgb": [255, 255, 0]},
    {"color": "green", "hex": "#0f0", "rgb": [0, 255, 0]},
    {"color": "cyan", "hex": "#0ff", "rgb": [0, 255, 255]},
    {"color": "blue", "hex": "#00f", "rgb": [0, 0, 255]},
    {"color": "magenta", "hex": "#f0f", "rgb": [255, 0, 255]},
    {"color": "white", "hex": "#fff", "rgb": [255, 255, 255]}
  ]
}

Human Style with Colored in the SEN Format

Sorted human style with colors is about as good as it gets but what if we deviate from strict JSON format and take a few shortcuts that Javascript and GraphQL allow such as unquoted strings and optional commas. The SEN format is that format. The oj application supports parsing and encoding in SEN format. It's not JSON but the conversion from SEN to JSON and the reverse is lossless. Getting rid of the extra quotes and unnecessary commas make the data easier to read and as a side benefit the SEN format takes up less space so transmission and disk space requirements are reduced when compared to JSON.

$ oj -p 80.3 -c -sen colors.json
{
  colors: [
    {color: black hex: "#000" rgb: [0 0 0]}
    {color: red hex: "#f00" rgb: [255 0 0]}
    {color: yellow hex: "#ff0" rgb: [255 255 0]}
    {color: green hex: "#0f0" rgb: [0 255 0]}
    {color: cyan hex: "#0ff" rgb: [0 255 255]}
    {color: blue hex: "#00f" rgb: [0 0 255]}
    {color: magenta hex: "#f0f" rgb: [255 0 255]}
    {color: white hex: "#fff" rgb: [255 255 255]}
  ]
}

Continue the Fight

Beauty is in the eye of the beholder. My preference is the pretty colored SEN format. You might have a different preference but let's continue the revolution together and get more pretty JSON out there. Use pretty JSON on web pages and in email. For the tool builders out there, offer the option for pretty JSON.

Note: In case you are wondering if the colored JSON HTML was written or colorized by hand, it was not. The -html option of oj was used to produce the colorized HTML for this article. It's a handy option when including JSON on web pages or in email.