{"id":938,"date":"2010-06-22T09:22:41","date_gmt":"2010-06-22T07:22:41","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=938"},"modified":"2013-04-03T16:48:25","modified_gmt":"2013-04-03T14:48:25","slug":"json-net-formatter","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/json-net-formatter","title":{"rendered":"Simple JSON .NET formatter"},"content":{"rendered":"<p>StringWalker class:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class StringWalker\r\n{\r\n    private readonly string _s;\r\n\r\n    public int Index { get; private set; }\r\n    public bool IsEscaped { get; private set; }\r\n    public char CurrentChar { get; private set; }\r\n\r\n    public StringWalker(string s)\r\n    {\r\n        _s = s;\r\n        this.Index = -1;\r\n    }\r\n\r\n    public bool MoveNext()\r\n    {\r\n        if (this.Index == _s.Length - 1)\r\n            return false;\r\n\r\n        if (IsEscaped == false)\r\n            IsEscaped = CurrentChar == '\\\\';\r\n        else\r\n            IsEscaped = false;\r\n        this.Index++;\r\n        CurrentChar = _s&#x5B;Index];\r\n        return true;\r\n    }\r\n};\r\n<\/pre>\n<p>IndentWriter class:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class IndentWriter\r\n{\r\n    private readonly StringBuilder _result = new StringBuilder();\r\n    private int _indentLevel;\r\n\r\n    public void Indent()\r\n    {\r\n        _indentLevel++;\r\n    }\r\n\r\n    public void UnIndent()\r\n    {\r\n        if (_indentLevel &gt; 0)\r\n            _indentLevel--;\r\n    }\r\n\r\n    public void WriteLine(string line)\r\n    {\r\n        _result.AppendLine(CreateIndent() + line);\r\n    }\r\n\r\n    private string CreateIndent()\r\n    {\r\n        StringBuilder indent = new StringBuilder();\r\n        for (int i = 0; i &lt; _indentLevel; i++)\r\n            indent.Append(&quot;    &quot;);\r\n        return indent.ToString();\r\n    }\r\n\r\n    public override string ToString()\r\n    {\r\n        return _result.ToString();\r\n    }\r\n};\r\n<\/pre>\n<p>JSON formatter class:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\r\npublic class JsonFormatter\r\n{\r\n    private readonly StringWalker _walker;\r\n    private readonly IndentWriter _writer = new IndentWriter();\r\n    private readonly StringBuilder _currentLine = new StringBuilder();\r\n    private bool _quoted;\r\n\r\n    public JsonFormatter(string json)\r\n    {\r\n        _walker = new StringWalker(json);\r\n        ResetLine();\r\n    }\r\n\r\n    public void ResetLine()\r\n    {\r\n        _currentLine.Length = 0;\r\n    }\r\n\r\n    public string Format()\r\n    {\r\n        while (MoveNextChar())\r\n        {\r\n            if (this._quoted == false &amp;&amp; this.IsOpenBracket())\r\n            {\r\n                this.WriteCurrentLine();\r\n                this.AddCharToLine();\r\n                this.WriteCurrentLine();\r\n                _writer.Indent();\r\n            }\r\n            else if (this._quoted == false &amp;&amp; this.IsCloseBracket())\r\n            {\r\n                this.WriteCurrentLine();\r\n                _writer.UnIndent();\r\n                this.AddCharToLine();\r\n            }\r\n            else if (this._quoted == false &amp;&amp; this.IsColon())\r\n            {\r\n                this.AddCharToLine();\r\n                this.WriteCurrentLine();\r\n            }\r\n            else\r\n            {\r\n                AddCharToLine();\r\n            }\r\n        }\r\n        this.WriteCurrentLine();\r\n        return _writer.ToString();\r\n    }\r\n\r\n    private bool MoveNextChar()\r\n    {\r\n        bool success = _walker.MoveNext();\r\n        if (this.IsApostrophe())\r\n        {\r\n            this._quoted = !_quoted;\r\n        }\r\n        return success;\r\n    }\r\n\r\n    public bool IsApostrophe()\r\n    {\r\n        return this._walker.CurrentChar == '&quot;' &amp;&amp; this._walker.IsEscaped == false;\r\n    }\r\n\r\n    public bool IsOpenBracket()\r\n    {\r\n        return this._walker.CurrentChar == '{'\r\n            || this._walker.CurrentChar == '&#x5B;';\r\n    }\r\n\r\n    public bool IsCloseBracket()\r\n    {\r\n        return this._walker.CurrentChar == '}'\r\n            || this._walker.CurrentChar == ']';\r\n    }\r\n\r\n    public bool IsColon()\r\n    {\r\n        return this._walker.CurrentChar == ',';\r\n    }\r\n\r\n    private void AddCharToLine()\r\n    {\r\n        this._currentLine.Append(_walker.CurrentChar);\r\n    }\r\n\r\n    private void WriteCurrentLine()\r\n    {\r\n        string line = this._currentLine.ToString().Trim();\r\n        if (line.Length &gt; 0)\r\n        {\r\n            _writer.WriteLine(line);\r\n        }\r\n        this.ResetLine();\r\n    }\r\n};\r\n<\/pre>\n<p>Few samples:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nConsole.WriteLine(new JsonFormatter(\r\n\t@&quot;{&quot;&quot;parameter&quot;&quot; : &quot;&quot;value&quot;&quot; , { &quot;&quot;parameter2&quot;&quot; : &quot;&quot;value2&quot;&quot; },{ &quot;&quot;parameter3&quot;&quot; : &quot;&quot;value3&quot;&quot; } }&quot;).Format());\r\nConsole.WriteLine(new JsonFormatter(\r\n\t@&quot;{&quot;&quot;parameter&quot;&quot;:&#x5B;&quot;&quot;value1&quot;&quot;,&quot;&quot;value2&quot;&quot;,&quot;&quot;value3&quot;&quot;] }&quot;).Format());\r\nConsole.WriteLine(new JsonFormatter(\r\n\t@&quot;{&quot;&quot;parameter&quot;&quot;: &quot;&quot;value with {brackets}&quot;&quot; }&quot;).Format());\r\nConsole.WriteLine(new JsonFormatter(\r\n    @&quot;{ &quot;&quot;hello&quot;&quot; : &quot;&quot;value with quotes \\&quot;&quot;{brackets} and back slash: \\\\&quot;&quot; }&quot;).Format());\r\n<\/pre>\n<p>&#8230;and results:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n{\r\n    &quot;parameter&quot; : &quot;value&quot; ,\r\n    {\r\n        &quot;parameter2&quot; : &quot;value2&quot;\r\n    },\r\n    {\r\n        &quot;parameter3&quot; : &quot;value3&quot;\r\n    }\r\n}\r\n\r\n{\r\n    &quot;parameter&quot;:\r\n    &#x5B;\r\n        &quot;value1&quot;,\r\n        &quot;value2&quot;,\r\n        &quot;value3&quot;\r\n    ]\r\n}\r\n\r\n{\r\n    &quot;parameter&quot;: &quot;value with {brackets}&quot;\r\n}\r\n\r\n{\r\n    &quot;hello&quot; : &quot;value with quotes \\&quot;{brackets} and back slash: \\\\&quot;\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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 &#8211; 1) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[15,31],"class_list":["post-938","post","type-post","status-publish","format-standard","hentry","category-programming","tag-c","tag-json"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/938"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=938"}],"version-history":[{"count":2,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/938\/revisions"}],"predecessor-version":[{"id":3898,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/938\/revisions\/3898"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=938"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=938"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=938"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}