Simple JSON .NET formatter

StringWalker class:

public class StringWalker
{
    private readonly string _s;

    public int Index { get; private set; }
    public bool IsEscaped { get; private set; }
    public char CurrentChar { get; private set; }

    public StringWalker(string s)
    {
        _s = s;
        this.Index = -1;
    }

    public bool MoveNext()
    {
        if (this.Index == _s.Length - 1)
            return false;

        if (IsEscaped == false)
            IsEscaped = CurrentChar == '\\';
        else
            IsEscaped = false;
        this.Index++;
        CurrentChar = _s[Index];
        return true;
    }
};

IndentWriter class:

public class IndentWriter
{
    private readonly StringBuilder _result = new StringBuilder();
    private int _indentLevel;

    public void Indent()
    {
        _indentLevel++;
    }

    public void UnIndent()
    {
        if (_indentLevel > 0)
            _indentLevel--;
    }

    public void WriteLine(string line)
    {
        _result.AppendLine(CreateIndent() + line);
    }

    private string CreateIndent()
    {
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < _indentLevel; i++)
            indent.Append("    ");
        return indent.ToString();
    }

    public override string ToString()
    {
        return _result.ToString();
    }
};

JSON formatter class:


public class JsonFormatter
{
    private readonly StringWalker _walker;
    private readonly IndentWriter _writer = new IndentWriter();
    private readonly StringBuilder _currentLine = new StringBuilder();
    private bool _quoted;

    public JsonFormatter(string json)
    {
        _walker = new StringWalker(json);
        ResetLine();
    }

    public void ResetLine()
    {
        _currentLine.Length = 0;
    }

    public string Format()
    {
        while (MoveNextChar())
        {
            if (this._quoted == false && this.IsOpenBracket())
            {
                this.WriteCurrentLine();
                this.AddCharToLine();
                this.WriteCurrentLine();
                _writer.Indent();
            }
            else if (this._quoted == false && this.IsCloseBracket())
            {
                this.WriteCurrentLine();
                _writer.UnIndent();
                this.AddCharToLine();
            }
            else if (this._quoted == false && this.IsColon())
            {
                this.AddCharToLine();
                this.WriteCurrentLine();
            }
            else
            {
                AddCharToLine();
            }
        }
        this.WriteCurrentLine();
        return _writer.ToString();
    }

    private bool MoveNextChar()
    {
        bool success = _walker.MoveNext();
        if (this.IsApostrophe())
        {
            this._quoted = !_quoted;
        }
        return success;
    }

    public bool IsApostrophe()
    {
        return this._walker.CurrentChar == '"' && this._walker.IsEscaped == false;
    }

    public bool IsOpenBracket()
    {
        return this._walker.CurrentChar == '{'
            || this._walker.CurrentChar == '[';
    }

    public bool IsCloseBracket()
    {
        return this._walker.CurrentChar == '}'
            || this._walker.CurrentChar == ']';
    }

    public bool IsColon()
    {
        return this._walker.CurrentChar == ',';
    }

    private void AddCharToLine()
    {
        this._currentLine.Append(_walker.CurrentChar);
    }

    private void WriteCurrentLine()
    {
        string line = this._currentLine.ToString().Trim();
        if (line.Length > 0)
        {
            _writer.WriteLine(line);
        }
        this.ResetLine();
    }
};

Few samples:

Console.WriteLine(new JsonFormatter(
	@"{""parameter"" : ""value"" , { ""parameter2"" : ""value2"" },{ ""parameter3"" : ""value3"" } }").Format());
Console.WriteLine(new JsonFormatter(
	@"{""parameter"":[""value1"",""value2"",""value3""] }").Format());
Console.WriteLine(new JsonFormatter(
	@"{""parameter"": ""value with {brackets}"" }").Format());
Console.WriteLine(new JsonFormatter(
    @"{ ""hello"" : ""value with quotes \""{brackets} and back slash: \\"" }").Format());

…and results:

{
    "parameter" : "value" ,
    {
        "parameter2" : "value2"
    },
    {
        "parameter3" : "value3"
    }
}

{
    "parameter":
    [
        "value1",
        "value2",
        "value3"
    ]
}

{
    "parameter": "value with {brackets}"
}

{
    "hello" : "value with quotes \"{brackets} and back slash: \\"
}

Tags: ,

7 Responses to “Simple JSON .NET formatter”

  1. Deni Says:

    From all the frameworks I’d tried, like newtonking, jayrock, json.net, and many others, this is the simplest solution ever. Thank you for this article.

  2. JustinBeersonu Says:

    Hey – I am really glad to find this. great job!

  3. andrey1de Says:

    Thank you very simple and elegant solution
    Old prog wolf Andy

  4. Brian Madsen Says:

    Great code! Thanks :)

  5. Coder Says:

    This code looks like it will fail with escaped quotes. The following is valid JSON syntax and will not be properly formatted with this code from the looks of it:

    { “hello” : “\”world\”” }

  6. Limilabs support Says:

    @Coder

    Corrected. Thanks!

  7. Chitti Says:

    Great Code ! Worked for me with minor tweaks thanks….

Questions?

Consider using our Q&A forum for asking any questions.