[C#]DataContractJsonSerializerのJsonを読みやすく整形する

#これはなに
C#でDataContractJsonSerializerを使いJsonを出力すると、1行になって出力されるので、
最低限見やすいように整形するコードです。

#コード
```csharp:json.cs
public class Json
{
    public static string Serialize(object target)
    {
        using (var stream = new MemoryStream())
        {
            var serializer = new DataContractJsonSerializer(target.GetType());
            serializer.WriteObject(stream, target);
            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }

    //2017/04/17 StringBuilder版
    public static string ToReadable(string json)
    {
        if (string.IsNullOrWhiteSpace(json)) return json;
        int i = 0;
        int indent = 0;
        int quoteCount = 0;
        int position = -1;
        var sb = new StringBuilder();
        int lastindex = 0;
        while (true)
        {
            if (i > 0 && json[i] == '"' && json[i - 1] != '\\') quoteCount++;

            if (quoteCount % 2 == 0) //is not value(quoted)
            {
                if (json[i] == '{' || json[i] == '[')
                {
                    indent++;
                    position = 1;
                }
                else if (json[i] == '}' || json[i] == ']')
                {
                    indent--;
                    position = 0;
                }
                else if (json.Length > i && json[i] == ',' && json[i + 1] == '"')
                {
                    position = 1;
                }
                if (position >= 0)
                {
                    sb.AppendLine(json.Substring(lastindex, i + position - lastindex));
                    sb.Append(new string(' ', indent * 4));
                    lastindex = i + position;
                    position = -1;
                }
            }

            i++;
            if (json.Length <= i)
            {
                sb.Append(json.Substring(lastindex));
                break;
            }

        }
        return sb.ToString();
    }

    public static string ToReadableOld(string json)
    {
        if (string.IsNullOrWhiteSpace(json)) return json;
        int i = 0;
        int indent = 0;
        int quoteCount = 0;
        int position = -1;
        string indentStr = "\n";
        while (true)
        {
            if (i > 0 && json[i] == '"' && json[i - 1] != '\\') quoteCount++;

            if (quoteCount % 2 == 0) //is not value(quoted)
            {
                if (json[i] == '{' || json[i] == '[')
                {
                    indent++;
                    position = 1;
                }
                else if (json[i] == '}' || json[i] == ']')
                {
                    indent--;
                    position = 0;
                }
                else if (json.Length > i && json[i] == ',' && json[i + 1] == '"')
                {
                    position = 1;
                }
                if (position >= 0)
                {
                    indentStr = "\n" + new string(' ', indent * 4);
                    json = json.Substring(0, i + position) + indentStr + json.Substring(i + position);
                    i += indentStr.Length - position;
                    position = -1;
                }
            }

            i++;
            if (json.Length <= i) break;
        }
        return json;
    }

    public static T Deserialize<T>(string json)
    {
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            return (T)serializer.ReadObject(stream);
        }
    }

    public static object Deserialize(Type type, string json)
    {
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            var serializer = new DataContractJsonSerializer(type);
            return serializer.ReadObject(stream);
        }
    }
}
```

#サンプル
```csharp:sample.cs
public class sample
{
    public int num { get; set; } = 100;
    public string str { get; set; } = "abc";
    public List<string> list { get; set; } = new List<string> { "A", "B", "C", "Escape:", "{", "}", "\"", "[", "]" };
}

private void test()
{
    var s = new sample();

    var json1 = Json.Serialize(s);
    Debug.WriteLine(json1);
    //{"list":["A","B","C","Escape:","{","}","\"","[","]"],"num":100,"str":"abc"}

    var json2 = Json.ToReadable(json1);
    Debug.WriteLine(json2);
    //{
    //    "list":[
    //        "A",
    //        "B",
    //        "C",
    //        "Escape:",
    //        "{",
    //        "}",
    //        "\"",
    //        "[",
    //        "]"
    //    ],
    //    "num":100,
    //    "str":"abc"
    //}
            
    var s1 = Json.Deserialize<sample>(json1);
    var s2 = Json.Deserialize<sample>(json2);
    Debug.WriteLine(Json.Serialize(s1) == Json.Serialize(s2));
    //True

}
```
#おわりに
とりあえず今のところ使っていて問題は起きていませんが、
ご指摘あればどんどんお願いします。

#追記 2017/04/17
大きいJsonを処理した際あまりに遅かったため、StringBuilderを使用したコードに
書き換えました。ToReadableが新しいコードでToReadableOldが古いコードです。
改行が\nから\r\nになっています。

```csharp:test.cs
var j = Json.Serializer.Serialize(s);
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
var t1 = Json.Serializer.ToReadableOld(j);
Debug.Log("Old:" + sw.ElapsedMilliseconds.ToString() + "ms");

sw.Restart();
var t2 = Json.Serializer.ToReadable(j).Replace("\r","");
Debug.Log("New:" + sw.ElapsedMilliseconds.ToString() + "ms");

Debug.Log("Old == New:" + (t1 == t2).ToString());
//Old:140653ms
//New:31ms
//Old == New:True
```