C#.Net 使用 JsonReader/JsonWriter 高性能解析/生成 Json 文档

  Swifter.Json 是由本人编写的高性能且多功能的 Json 解析库。下图是 Swifter.Json 与 .Net 平台上的其他 Json 库性能对比:

  

  在 Swifter.Json 近期更新的 API 中增加了直接构建 JSON 和直接解析 JSON 的方法。下面演示这两个方法如何使用:

  1:使用 JsonWriter 直接生成 Json 文档:

using Swifter.Json;
using Swifter.Tools;
using System;

public class Demo
{
    public static void Main()
    {
        var jsonWriter = JsonFormatter.CreateJsonWriter();

        jsonWriter.WriteBeginObject();

        jsonWriter.WritePropertyName("Id");
        jsonWriter.WriteInt32(123);

        jsonWriter.WritePropertyName("Name");
        jsonWriter.WriteString("Dogwei");

        jsonWriter.WriteEndObject();

        Console.WriteLine(jsonWriter.HGCache.ToStringEx());



        /**
         * Output : {"Id":123,"Name":"Dogwei"}
         */
    }
}

  注意:使用 JsonWriter 时应将 jsonWriter 保存起来,重复使用,这样才能将性能最大化。

  2:使用 JsonReader 直接遍历 Json 文档:

using Swifter.Json;
using System;
using System.IO;

public class Demo
{
    public static void Main()
    {
        using var textReader = new StringReader("{\"Id\":123,\"Name\":\"Dogwei\"}");

        var jsonReader = JsonFormatter.CreateJsonReader(textReader);

        if (jsonReader.TryReadBeginObject())
        {
            while (!jsonReader.TryReadEndObject())
            {
                var name = jsonReader.ReadPropertyName();

                switch (name)
                {
                    case "Id":
                        Console.WriteLine($"{name}: {jsonReader.ReadInt32()}");
                        break;
                    case "Name":
                        Console.WriteLine($"{name}: {jsonReader.ReadString()}");
                        break;
                    default:
                        Console.WriteLine($"{name}: {jsonReader.DirectRead()}");
                        break;
                }
            }
        }

        /** 
         * Output : 
         * Id: 123
         * Name: Dogwei
         */
    }
}

  3:更简单的遍历 Json 文档:

using Swifter.Json;
using System;
using System.IO;

public class Demo
{
    public static void Main()
    {
        using var textReader = new StringReader("[{\"Id\":1,\"Name\":\"Dogwei\"},{\"Id\":2,\"Name\":\"ChenXinwei\"},{\"Id\":3,\"Name\":\"Swifter.Json\"}]");

        var jsonReader = JsonFormatter.CreateJsonReader(textReader);

        foreach (var item in jsonReader.ReadArray())
        {
            foreach (var pair in item.ReadObject())
            {
                var name = pair.Key;
                var value = pair.Value.DirectRead();

                Console.WriteLine($"{name} : {value}");
            }
        }

        /** 
         * Output : 
         * Id : 1
         * Name : Dogwei
         * Id : 2
         * Name : ChenXinwei
         * Id : 3
         * Name : Swifter.Json
         */
    }
}

  注意:JsonReader 是原始提供的是原始解析 Json 的方法,它性能极快,也正因此,它每个读取方法都会偏移游标,不读取就不偏移,解析 Json 时所有的 '值' 都必须读且只读一次!如上例:如果 pair.Value.DirectRead() 调用了两次,或者一次都没调用,那么就会解析出错!

  下例做一下简单的性能对比:

using Newtonsoft.Json;
using Swifter.Json;
using System;
using System.Diagnostics;
using System.IO;

public class Demo
{
    public static void Main()
    {
        var swifterWriter = JsonFormatter.CreateJsonWriter();

        var newtonsoftStringWriter = new StringWriter();
        var newtonsoftWriter = new JsonTextWriter(newtonsoftStringWriter);

        while (true)
        {
            var stopwatch = Stopwatch.StartNew();

            for (int i = 0; i < 1000000; i++)
            {
                newtonsoftWriter.WriteStartObject();

                newtonsoftWriter.WritePropertyName("Id");
                newtonsoftWriter.WriteValue(123);

                newtonsoftWriter.WritePropertyName("Name");
                newtonsoftWriter.WriteValue("Dogwei");

                newtonsoftWriter.WriteEndObject();

                newtonsoftStringWriter.GetStringBuilder().Length = 0;
            }

            Console.WriteLine($"Newtonsoft.Json : {stopwatch.ElapsedMilliseconds}");

            stopwatch = Stopwatch.StartNew();

            for (int i = 0; i < 1000000; i++)
            {
                swifterWriter.WriteBeginObject();

                swifterWriter.WritePropertyName("Id");
                swifterWriter.WriteInt32(123);

                swifterWriter.WritePropertyName("Name");
                swifterWriter.WriteString("Dogwei");

                swifterWriter.WriteEndObject();

                swifterWriter.Clear();
            }

            Console.WriteLine($"Swifter.Json : {stopwatch.ElapsedMilliseconds}");

            Console.ReadKey();
        }

        /**
         * Output:
         * Newtonsoft.Json : 197
         * Swifter.Json : 64
         */
    }
}
using Newtonsoft.Json;
using Swifter.Json;
using System;
using System.Diagnostics;
using System.IO;

public class Demo
{
    public static void Main()
    {
        while (true)
        {
            var stopwatch = Stopwatch.StartNew();

            for (int i = 0; i < 1000000; i++)
            {
                var jsonReader = new JsonTextReader(new StringReader("{\"Id\":123,\"Name\":\"Dogwei\"}"));

                while (jsonReader.Read())
                {
                    if (jsonReader.TokenType == JsonToken.PropertyName)
                    {
                        var name = (string)jsonReader.Value;

                        switch (name)
                        {
                            case "Id":
                                jsonReader.ReadAsInt32();
                                break;
                            case "Name":
                                jsonReader.ReadAsString();
                                break;
                            default:
                                jsonReader.Skip();
                                break;
                        }
                    }
                }
            }

            Console.WriteLine($"Newtonsoft.Json : {stopwatch.ElapsedMilliseconds}");

            stopwatch = Stopwatch.StartNew();

            for (int i = 0; i < 1000000; i++)
            {
                var jsonReader = JsonFormatter.CreateJsonReader(new StringReader("{\"Id\":123,\"Name\":\"Dogwei\"}"));

                if (jsonReader.TryReadBeginObject())
                {
                    while (!jsonReader.TryReadEndObject())
                    {
                        var name = jsonReader.ReadPropertyName();

                        switch (name)
                        {
                            case "Id":
                                jsonReader.ReadInt32();
                                break;
                            case "Name":
                                jsonReader.ReadString();
                                break;
                            default:
                                jsonReader.SkipValue();
                                break;
                        }
                    }
                }
            }

            Console.WriteLine($"Swifter.Json : {stopwatch.ElapsedMilliseconds}");

            Console.ReadKey();
        }

        /**
         * Output:
         * Newtonsoft.Json : 759
         * Swifter.Json : 161
         */
    }
}

  特别强调:这两种方式都是提供给有特别需求的用户,普通用户不建议使用,因为使用门槛较高,不利于维护!个人建议是定义模型,然后不管是序列化和反序列化都使用模型!这样在保证性能的情况下,使用也变得简单,易于维护。

 

  最后附上 Swifter.Json 的开源地址:https://github.com/Dogwei/Swifter.Json 希望大家支持一下。

posted @ 2019-07-24 16:28  陈鑫伟  阅读(2078)  评论(5编辑  收藏  举报