Formatting JSON without external libraries

Formatting JSON without external libraries

Most programming languages today have great JSON support. If it isn't built into the language, there is a de facto standard library you can add to your project. Included in these libraries is a formatting function. For the sake of space, most of these libraries will have your JSON minified by default. For larger documents, this quickly becomes very unreadable to users.

Because of this, these libraries have a JSON format function. However, it isn't a terribly hard problem to solve. If all you need to do is format a JSON document that is already a string, many of these libraries would force you to parse the document into memory and then write it out.

Below is a function that formats any valid JSON string. By default, it indents it by two spaces but that is fully parameterized in this function. It is written in C# because it is one of the few popular languages that relies on a 3rd party library for its JSON functionality. This could also easily be rewritten in almost any imperative language.

public static string FormatJson(string json, char indent = ' ', int times = 2)
{
	var indentation = 0;
	var quoteCount = 0;
	var indentString = string.Concat(Enumerable.Repeat(indent, times));
	var result = "";
	foreach (var ch in json) {
		switch (ch) {
			case '"':
				quoteCount++;
				result += ch;
			break;
			case ',':
				if (quoteCount % 2 == 0) {
					result += ch + Environment.NewLine + 
                    string.Concat(Enumerable.Repeat(indentString, indentation));
				}
			break;
			case '{':
			case '[':
				var openFormatted = string.Concat(Enumerable.Repeat(indentString, ++indentation)) 
                + indent;
				result += string.Format("{0}{1}{2}", ch, Environment.NewLine, openFormatted);
			break;
			case '}':
			case ']':
				var closeFormatted = string.Concat(Enumerable.Repeat(indentString, --indentation));
				result += string.Format("{0}{1}{2}", Environment.NewLine, closeFormatted, ch);
			break;
			default:
				result += ch;
			break;
		}
	}
	return result;
}