Coding a JSON formatter

If you’re anything like me then you probably have a load of websites listed in your favourites that handle simple dev utility tasks like formatting JSON, viewing the contents of a JWT, testing regular expressions, etc.

My plan for the next couple blogs is to code an electron app using Vue3 that does a few of these tasks for me, starting with a JSON formatter.

I’ve done something relatively similar in Coding a JSON to C# Parser which is also worth a read as the implementation is very different.

Pre-processing

When provided with some unformatted JSON, the first thing we want to do is pre-process. Generally when something needs formatting, it’s likely got an incorrect number of spaces sporadically placed. Strings pose a potential problem here as the whitespace within them is more than likely correct. To deal with this problem I created a regex — using regexr 😡 — to extract the strings for later use.

json.replace(/".*?"/, extractString); 

If you’re interested in learning regex — it’s really not as difficult as it’s made out to be — have a read through Regex from beginner to best on your team in one blog.

The extractString function does the following:

let jsonStrings = [];

function extractString(m) {
  return "<" + jsonStrings.push(m) + ">";
}

It replaces the strings with the index of the jsonStrings array. So some json that looks like the following:

{
   "name": "Luke",
   "height": 188
}

to:

{ 
    <1>:<2>,
    <3>:188
}

We will later push those strings back into the final output.

Now we can write another regex to remove any additional space:

json.replace(/\s+/g, "")

The formatting

Now that our JSON has been pre-processed we should be in a good position to start adding the correct spacing. The bulk of the algorithm here is pretty simple:

output = ""
indent = 0
if { or [ 
    indent++
    add to output
    add new line
    add indent
if } or ]
    indent--
    add new line
    add indent
    add to output
if ,
    add to output
    add new line (Not 100% needed, depends on preference)
if :
   add to output
   add space
else 
   add to output

In JavaScript:

  for (let i = 0; i < newJson.length; i++) {
    const current = newJson.charAt(i);
    if (current === "{" || current === "[") {
      indent++;
      out += current + "\n" + addTabs(indent);
    } else if (current === "}" || current === "]") {
      indent--;
      out += "\n" + addTabs(indent) + current;
    } else if (current === ",") {
      out += ",\n" + addTabs(indent);
    } else if (current === ":") {
      out += ": ";
    } else {
      out += current;
    }
  }

Injecting the strings

Now that we have some JSON that is formatted like:

{ 
    <1>:<2>,
    <3>:188
}

it’s a case pushing those strings we pulled out back into the json, replacing the numbers wrapped in angled brackets. Guess what we’re going to use for this? Regex:

let out = out.replace(/<(\d+)>/g, currentString)

Where the currentString function uses the index passed in to grab the current string:

function currentString(value, index) {
  return jsonStrings[index - 1];
}

And there you have it. That’s a pretty handy JSON formatter, no need to rely on those websites to do it for you!

Here’s my application working so far:

And that’s pretty much all there is to it, if you liked this blog then please sign up for my newsletter and join an awesome community!

2 comments

Leave a Reply