在C#中解析JSON的最高效方法

10

我想知道在C#中解析JSON最有效的方法是什么?通过更高效,我指的是响应时间较低的方法。我正在尝试使用一些方法解析大量数据,但这些方法的响应时间都很长。有人能告诉我以下方法之间的区别吗?是否有其他选项可以让我以更短的响应时间解析JSON?

选项1:

HttpWebRequest request = WebRequest.Create(jsonURL) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    if (response.StatusCode != HttpStatusCode.OK)
        throw new Exception(String.Format(
        "Server error (HTTP {0}: {1}).",
        response.StatusCode,
        response.StatusDescription));
    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(obj));
    object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
}  

选项2:

var json = new WebClient().DownloadString(jsonURL);
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(obj));
    object objResponse = jsonSerializer.ReadObject(ms);
}  

那么...你的数据有多大?现在先定义一下你所说的“高”响应时间是什么意思?你已经确定瓶颈是网络还是处理了吗? - Laurent S.
尝试使用ServiceStack、Json.Net、JavaScriptSerializer等工具并查看结果。 - I4V
1
http://www.servicestack.net/benchmarks/ - I4V
5个回答

13
您可以在以下链接中找到比较。
测试的库:

http://sagistech.blogspot.com/2010/03/parsing-twitter-json-comparing-c.html

  • Json.NET - 一款流行的C# JSON库。
  • Gapi.NET - Gapi.NET不是一个JSON解析库,但它包含了JSON解析例程。
  • Procurios - 又一个C# JSON库。也可以参考这篇博客文章来学习如何使用它来解析Twitter数据。
  • JavaScriptSerializer - .NET 3.5内置的JSON解析器。
  • DataContractJsonSerializer - .NET 3.5内置的JSON解析器。
  • AjaxPro - 一个C# AJAX库。

enter image description here


更新:

根据Matt Johnson的评论添加了这些信息。

http://theburningmonk.com/2011/11/performance-test-json-serializers-part-ii/


1
不要忘记 ServiceStack.Text。这里有基准测试结果 - Matt Johnson-Pint
感谢您的回答!根据Sagi的博客,Json比DataContractJsonSerializer更好,但根据Matt的链接,DataContract更好。您有机会比较过Gapi.NET和ServiceStack.Text吗? - Gonzalo
1
@Gonzalo - 就我个人而言,我使用JSON.Net。所有这些基准测试都已过时,我没有看到最近的一个 - 所以我不知道谁是目前最快的。无论如何,这些只是毫秒差异。JSON.Net是最广泛实现的,非常稳定和灵活的。我更重视这些特点,而不是原始性能。 - Matt Johnson-Pint
1
甚至微软也已经停止使用 DataContractJsonSerializerJavascriptSerializer。所有新的东西(如MVC4)都带有JSON.Net。 - Matt Johnson-Pint
JSON.NET 的灵活性非常棒,我认为最近的版本都在注重提高性能。 - Brandon
@MattJohnson 经过一些研究和调试我的代码,我发现使用DataContractJsonSerializer和JSON.Net之间没有太大的区别。正是请求JSON数据使响应时间如此之长 new WebClient().DownloadString(jsonURL),并且这在两个库中都是必要的。我正在尝试通过查看这里来改善这行中的响应时间,但我想我能做的不多。 - Gonzalo

1

目前还处于早期阶段,但我在Json.NET的基础上构建了一个代码生成器,消除了反射并将反序列化速度提高了4倍。

请查看CGbR JSON target

[DataContract]
public partial class Root
{
    [DataMember]
    public int Number { get; set; }

    [DataMember]
    public Partial[] Partials { get; set; }

    [DataMember]
    public IList<ulong> Numbers { get; set; }
}

将生成一个部分类:
public Root FromJson(JsonReader reader)
{
    while (reader.Read())
    {
        // Break on EndObject
        if (reader.TokenType == JsonToken.EndObject)
            break;

        // Only look for properties
        if (reader.TokenType != JsonToken.PropertyName)
            continue;

        switch ((string) reader.Value)
        {
            case "Number":
                reader.Read();
                Number = Convert.ToInt32(reader.Value);
                break;

            case "Partials":
                reader.Read(); // Read token where array should begin
                if (reader.TokenType == JsonToken.Null)
                    break;
                var partials = new List<Partial>();
                while (reader.Read() && reader.TokenType == JsonToken.StartObject)
                    partials.Add(new Partial().FromJson(reader));
                Partials = partials.ToArray();
                break;

            case "Numbers":
                reader.Read(); // Read token where array should begin
                if (reader.TokenType == JsonToken.Null)
                    break;
                var numbers = new List<ulong>();
                while (reader.Read() && reader.TokenType != JsonToken.EndArray)
                    numbers.Add(Convert.ToUInt64(reader.Value));
                Numbers = numbers;
                break;

        }
    }

    return this;
}

1
第一种方法有机会减少数据的副本。但我难以相信任何一种方法都会产生可衡量的差异。你真正的成本将是网络成本。

0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Example
{
public static class JavascriptSerializator
{
    /// <summary>
    /// Serializes object to JSON from Microsoft
    /// </summary>
    /// <param name="objectForSerialization"></param>
    /// <returns></returns>
    public static string SerializeMJSON(this object objectForSerialization)
    {
        try
        {
            System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer();

            return s.Serialize(objectForSerialization);
        }
        catch (Exception ex)
        {
            /// Handle exception and throw it ...
        }

    }

    /// <summary>
    /// Deserializes object from Microsoft JSON string
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="str"></param>
    /// <returns></returns>
    public static T DeserializeMJSON<T>(this string str)
    {
        try
        {
            System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer();

            return s.Deserialize<T>(str);
        }
        catch (Exception ex)
        {
            //// Handle the exception here...
        }

    }
}

}


1
OP很注重效率。这是一种方法,可能不是最有效的方法。 - CodesInChaos

0

出于好奇,我曾让JSON.NET 5.0 r8和我自己编写的(仅约500行代码)玩具JSON解析器处理各种带有或不带有循环的JSON文件大小,从几十个字符到一个180mb的JSON文件,例如“真实”数据。

这里可以找到样本数据(包括12mb的JSON文件,但不包括可以在其他地方找到的180mb的文件),以及相关详细信息,例如从流中解析并反序列化为POCO(强类型)对象的示例:

https://github.com/ysharplanguage/FastJsonParser

希望能有所帮助。

另外,Chamika 在他的评论中已经提供了一些好链接要知道。

编辑

在我忘记之前(或者以防被忽视),这是我认为必须知道/必须阅读的内容,即尽可能避免强调CLR的大型对象堆,特别是在Web服务器环境下,由于您的代码消耗JSON的流式阅读的重要性:

http://insidethecpu.wordpress.com/2013/06/19/json-parsing/

P.P.S. (因此在 Program.cs 中非常后面的测试,用来测试/展示我链接到的玩具解析器)

希望有所帮助!


这是一个不错的网站:https://michaelscodingspot.com/the-battle-of-c-to-json-serializers-in-net-core-3/ - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接