English 中文(简体)
您在.NET中使用哪个JSON库表现良好?[已关闭]
原标题:
  • 时间:2009-02-20 20:45:13
  •  标签:

我们不允许寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,使其可以回答事实和引用资料。

Closed 7 years ago.

我很想听听社区中的人们在.NET中使用的JSON库是什么?我需要解析/序列化一些JSON对象图形,以实际的.NET类型从.NET(C#)内部。我可以自己编写,但如果有一些可靠的库,我想听听你的评论。我看到了json.org网站上的库列表,但这是一个相当大的列表,社区通常很擅长筛选出竞争者和假冒者。

任何关于你在图书馆的经历的细节(优缺点)都将非常有帮助。--提前谢谢。

问题回答

我过去成功地使用过Json.NET

从网站中的示例:

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": new Date(1230422400000),
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);

至少有两个内置于框架中。

较新的:System.Runtime.Serialization.Json

而且更老的:System.Web.Script.Serialization

我更喜欢不依赖第三方库。我每天都使用JSON,从未需要比框架中已有的更多的东西。

我使用 DataContractJsonSerializerSystem.ServiceModel.Web.dll 程序集中编写了自己的 JSON 序列化程序(这是 WCF 的组件,包含在 .NET 3.5 中作为标准程序集,并在 .NET 3.5 SP1 Client Profile 中提供)(在 .NET 4.0 和 Silverlight 4 中,它已移动到 System.Runtime.Serialization.dll)。

using System.IO;
using System.Runtime.Serialization.Json;

public class JsonObjectSerializer 
{
    public string Serialize<T>(T instance) where T : class
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        using (var memoryStream = new MemoryStream())
        {
            serializer.WriteObject(memoryStream, instance);

            memoryStream.Flush();
            memoryStream.Position = 0;

            using (var reader = new StreamReader(memoryStream))
            {
                return reader.ReadToEnd();
            }
        }
    }

    public T Deserialize<T>(string serialized) where T : class
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        using (var memoryStream = new MemoryStream())
        {
            using (var writer = new StreamWriter(memoryStream))
            {
                writer.Write(serialized);
                writer.Flush();

                memoryStream.Position = 0;

                return serializer.ReadObject(memoryStream) as T;
            }
        }
    }
}

你也应该尝试一下我的ServiceStack的JsonSerializer - 它是目前最快的.NET JSON序列化程序,根据主要JSON序列化程序的基准测试,并支持对任何POCO类型、DataContracts、列表/字典、接口、继承、晚期绑定对象(包括匿名类型)等进行序列化。

基本例子:

Customer customer = new Customer { Name="Joe Bloggs", Age=31 };
string json = customer.ToJson();
Customer fromJson = json.FromJson<Customer>(json); 

请查看 .NET 3.5 中包含的 System.Runtime.Serialization.Json 命名空间。

我在谷歌上键入了“json”,而顶部链接指向json.org,该网站提供了一个看起来很好的单一实用类。

using System;
using System.Collections;
using System.Globalization;
using System.Text;

namespace Procurios.Public
{
    /// <summary>
    /// This class encodes and decodes JSON strings.
    /// Spec. details, see http://www.json.org/
    /// 
    /// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
    /// All numbers are parsed to doubles.
    /// </summary>
    public class JSON
    {
        public const int TOKEN_NONE = 0; 
        public const int TOKEN_CURLY_OPEN = 1;
        public const int TOKEN_CURLY_CLOSE = 2;
        public const int TOKEN_SQUARED_OPEN = 3;
        public const int TOKEN_SQUARED_CLOSE = 4;
        public const int TOKEN_COLON = 5;
        public const int TOKEN_COMMA = 6;
        public const int TOKEN_STRING = 7;
        public const int TOKEN_NUMBER = 8;
        public const int TOKEN_TRUE = 9;
        public const int TOKEN_FALSE = 10;
        public const int TOKEN_NULL = 11;

        private const int BUILDER_CAPACITY = 2000;

        /// <summary>
        /// Parses the string json into a value
        /// </summary>
        /// <param name="json">A JSON string.</param>
        /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
        public static object JsonDecode(string json)
        {
            bool success = true;

            return JsonDecode(json, ref success);
        }

        /// <summary>
        /// Parses the string json into a value; and fills  success  with the successfullness of the parse.
        /// </summary>
        /// <param name="json">A JSON string.</param>
        /// <param name="success">Successful parse?</param>
        /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
        public static object JsonDecode(string json, ref bool success)
        {
            success = true;
            if (json != null) {
                char[] charArray = json.ToCharArray();
                int index = 0;
                object value = ParseValue(charArray, ref index, ref success);
                return value;
            } else {
                return null;
            }
        }

        /// <summary>
        /// Converts a Hashtable / ArrayList object into a JSON string
        /// </summary>
        /// <param name="json">A Hashtable / ArrayList</param>
        /// <returns>A JSON encoded string, or null if object  json  is not serializable</returns>
        public static string JsonEncode(object json)
        {
            StringBuilder builder = new StringBuilder(BUILDER_CAPACITY);
            bool success = SerializeValue(json, builder);
            return (success ? builder.ToString() : null);
        }

        protected static Hashtable ParseObject(char[] json, ref int index, ref bool success)
        {
            Hashtable table = new Hashtable();
            int token;

            // {
            NextToken(json, ref index);

            bool done = false;
            while (!done) {
                token = LookAhead(json, index);
                if (token == JSON.TOKEN_NONE) {
                    success = false;
                    return null;
                } else if (token == JSON.TOKEN_COMMA) {
                    NextToken(json, ref index);
                } else if (token == JSON.TOKEN_CURLY_CLOSE) {
                    NextToken(json, ref index);
                    return table;
                } else {

                    // name
                    string name = ParseString(json, ref index, ref success);
                    if (!success) {
                        success = false;
                        return null;
                    }

                    // :
                    token = NextToken(json, ref index);
                    if (token != JSON.TOKEN_COLON) {
                        success = false;
                        return null;
                    }

                    // value
                    object value = ParseValue(json, ref index, ref success);
                    if (!success) {
                        success = false;
                        return null;
                    }

                    table[name] = value;
                }
            }

            return table;
        }

        protected static ArrayList ParseArray(char[] json, ref int index, ref bool success)
        {
            ArrayList array = new ArrayList();

            // [
            NextToken(json, ref index);

            bool done = false;
            while (!done) {
                int token = LookAhead(json, index);
                if (token == JSON.TOKEN_NONE) {
                    success = false;
                    return null;
                } else if (token == JSON.TOKEN_COMMA) {
                    NextToken(json, ref index);
                } else if (token == JSON.TOKEN_SQUARED_CLOSE) {
                    NextToken(json, ref index);
                    break;
                } else {
                    object value = ParseValue(json, ref index, ref success);
                    if (!success) {
                        return null;
                    }

                    array.Add(value);
                }
            }

            return array;
        }

        protected static object ParseValue(char[] json, ref int index, ref bool success)
        {
            switch (LookAhead(json, index)) {
                case JSON.TOKEN_STRING:
                    return ParseString(json, ref index, ref success);
                case JSON.TOKEN_NUMBER:
                    return ParseNumber(json, ref index, ref success);
                case JSON.TOKEN_CURLY_OPEN:
                    return ParseObject(json, ref index, ref success);
                case JSON.TOKEN_SQUARED_OPEN:
                    return ParseArray(json, ref index, ref success);
                case JSON.TOKEN_TRUE:
                    NextToken(json, ref index);
                    return true;
                case JSON.TOKEN_FALSE:
                    NextToken(json, ref index);
                    return false;
                case JSON.TOKEN_NULL:
                    NextToken(json, ref index);
                    return null;
                case JSON.TOKEN_NONE:
                    break;
            }

            success = false;
            return null;
        }

        protected static string ParseString(char[] json, ref int index, ref bool success)
        {
            StringBuilder s = new StringBuilder(BUILDER_CAPACITY);
            char c;

            EatWhitespace(json, ref index);

            // "
            c = json[index++];

            bool complete = false;
            while (!complete) {

                if (index == json.Length) {
                    break;
                }

                c = json[index++];
                if (c ==  " ) {
                    complete = true;
                    break;
                } else if (c ==  \ ) {

                    if (index == json.Length) {
                        break;
                    }
                    c = json[index++];
                    if (c ==  " ) {
                        s.Append( " );
                    } else if (c ==  \ ) {
                        s.Append( \ );
                    } else if (c ==  / ) {
                        s.Append( / );
                    } else if (c ==  b ) {
                        s.Append(  );
                    } else if (c ==  f ) {
                        s.Append( f );
                    } else if (c ==  n ) {
                        s.Append( 
 );
                    } else if (c ==  r ) {
                        s.Append( 
 );
                    } else if (c ==  t ) {
                        s.Append( 	 );
                    } else if (c ==  u ) {
                        int remainingLength = json.Length - index;
                        if (remainingLength >= 4) {
                            // parse the 32 bit hex into an integer codepoint
                            uint codePoint;
                            if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) {
                                return "";
                            }
                            // convert the integer codepoint to a unicode char and add to string
                            s.Append(Char.ConvertFromUtf32((int)codePoint));
                            // skip 4 chars
                            index += 4;
                        } else {
                            break;
                        }
                    }

                } else {
                    s.Append(c);
                }

            }

            if (!complete) {
                success = false;
                return null;
            }

            return s.ToString();
        }

        protected static double ParseNumber(char[] json, ref int index, ref bool success)
        {
            EatWhitespace(json, ref index);

            int lastIndex = GetLastIndexOfNumber(json, index);
            int charLength = (lastIndex - index) + 1;

            double number;
            success = Double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);

            index = lastIndex + 1;
            return number;
        }

        protected static int GetLastIndexOfNumber(char[] json, int index)
        {
            int lastIndex;

            for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
                if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) {
                    break;
                }
            }
            return lastIndex - 1;
        }

        protected static void EatWhitespace(char[] json, ref int index)
        {
            for (; index < json.Length; index++) {
                if (" 	

".IndexOf(json[index]) == -1) {
                    break;
                }
            }
        }

        protected static int LookAhead(char[] json, int index)
        {
            int saveIndex = index;
            return NextToken(json, ref saveIndex);
        }

        protected static int NextToken(char[] json, ref int index)
        {
            EatWhitespace(json, ref index);

            if (index == json.Length) {
                return JSON.TOKEN_NONE;
            }

            char c = json[index];
            index++;
            switch (c) {
                case  { :
                    return JSON.TOKEN_CURLY_OPEN;
                case  } :
                    return JSON.TOKEN_CURLY_CLOSE;
                case  [ :
                    return JSON.TOKEN_SQUARED_OPEN;
                case  ] :
                    return JSON.TOKEN_SQUARED_CLOSE;
                case  , :
                    return JSON.TOKEN_COMMA;
                case  " :
                    return JSON.TOKEN_STRING;
                case  0 : case  1 : case  2 : case  3 : case  4 : 
                case  5 : case  6 : case  7 : case  8 : case  9 :
                case  - : 
                    return JSON.TOKEN_NUMBER;
                case  : :
                    return JSON.TOKEN_COLON;
            }
            index--;

            int remainingLength = json.Length - index;

            // false
            if (remainingLength >= 5) {
                if (json[index] ==  f  &&
                    json[index + 1] ==  a  &&
                    json[index + 2] ==  l  &&
                    json[index + 3] ==  s  &&
                    json[index + 4] ==  e ) {
                    index += 5;
                    return JSON.TOKEN_FALSE;
                }
            }

            // true
            if (remainingLength >= 4) {
                if (json[index] ==  t  &&
                    json[index + 1] ==  r  &&
                    json[index + 2] ==  u  &&
                    json[index + 3] ==  e ) {
                    index += 4;
                    return JSON.TOKEN_TRUE;
                }
            }

            // null
            if (remainingLength >= 4) {
                if (json[index] ==  n  &&
                    json[index + 1] ==  u  &&
                    json[index + 2] ==  l  &&
                    json[index + 3] ==  l ) {
                    index += 4;
                    return JSON.TOKEN_NULL;
                }
            }

            return JSON.TOKEN_NONE;
        }

        protected static bool SerializeValue(object value, StringBuilder builder)
        {
            bool success = true;

            if (value is string) {
                success = SerializeString((string)value, builder);
            } else if (value is Hashtable) {
                success = SerializeObject((Hashtable)value, builder);
            } else if (value is ArrayList) {
                success = SerializeArray((ArrayList)value, builder);
            } else if (IsNumeric(value)) {
                success = SerializeNumber(Convert.ToDouble(value), builder);
            } else if ((value is Boolean) && ((Boolean)value == true)) {
                builder.Append("true");
            } else if ((value is Boolean) && ((Boolean)value == false)) {
                builder.Append("false");
            } else if (value == null) {
                builder.Append("null");
            } else {
                success = false;
            }
            return success;
        }

        protected static bool SerializeObject(Hashtable anObject, StringBuilder builder)
        {
            builder.Append("{");

            IDictionaryEnumerator e = anObject.GetEnumerator();
            bool first = true;
            while (e.MoveNext()) {
                string key = e.Key.ToString();
                object value = e.Value;

                if (!first) {
                    builder.Append(", ");
                }

                SerializeString(key, builder);
                builder.Append(":");
                if (!SerializeValue(value, builder)) {
                    return false;
                }

                first = false;
            }

            builder.Append("}");
            return true;
        }

        protected static bool SerializeArray(ArrayList anArray, StringBuilder builder)
        {
            builder.Append("[");

            bool first = true;
            for (int i = 0; i < anArray.Count; i++) {
                object value = anArray[i];

                if (!first) {
                    builder.Append(", ");
                }

                if (!SerializeValue(value, builder)) {
                    return false;
                }

                first = false;
            }

            builder.Append("]");
            return true;
        }

        protected static bool SerializeString(string aString, StringBuilder builder)
        {
            builder.Append(""");

            char[] charArray = aString.ToCharArray();
            for (int i = 0; i < charArray.Length; i++) {
                char c = charArray[i];
                if (c ==  " ) {
                    builder.Append("\"");
                } else if (c ==  \ ) {
                    builder.Append("\\");
                } else if (c ==   ) {
                    builder.Append("\b");
                } else if (c ==  f ) {
                    builder.Append("\f");
                } else if (c ==  
 ) {
                    builder.Append("\n");
                } else if (c ==  
 ) {
                    builder.Append("\r");
                } else if (c ==  	 ) {
                    builder.Append("\t");
                } else {
                    int codepoint = Convert.ToInt32(c);
                    if ((codepoint >= 32) && (codepoint <= 126)) {
                        builder.Append(c);
                    } else {
                        builder.Append("\u" + Convert.ToString(codepoint, 16).PadLeft(4,  0 ));
                    }
                }
            }

            builder.Append(""");
            return true;
        }

        protected static bool SerializeNumber(double number, StringBuilder builder)
        {
            builder.Append(Convert.ToString(number, CultureInfo.InvariantCulture));
            return true;
        }

        /// <summary>
        /// Determines if a given object is numeric in any way
        /// (can be integer, double, null, etc). 
        /// 
        /// Thanks to mtighe for pointing out Double.TryParse to me.
        /// </summary>
        protected static bool IsNumeric(object o)
        {
            double result;

            return (o == null) ? false : Double.TryParse(o.ToString(), out result);
        }
    }
}

我使用了 System.Web.Helpers.Json 进行编码和解码。它解码成动态类型,非常适配 JavaScript 的动态数据。





相关问题
热门标签