2009-02-20 62 views
30

我有興趣聽取社區什麼JSON庫人們一直在使用.NET的內部?我需要將.NET(C#)中的一些JSON對象圖解析/序列化爲實際的.NET類型。我可以推出自己的產品,但如果有人使用了一些堅實的圖書館,我想聽聽您的意見。我在json.org網站上看到了一些圖書館列表,但這是一個相當大的列表,社區通常善於審覈僞冒者的競爭者什麼JSON庫很適合你的.NET?

您的圖書館經驗的任何細節(優點/缺點)會非常有幫助。 - 提前致謝。

回答

22

我用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); 
+5

只是爲了記錄,如果有人遇到這種情況,''Expiry':new Date(1230422400000)`是**不是**有效的JSON。 – 2011-05-09 19:00:21

+0

@ RichardMarskell-Drackir,是的。 JSON.NET是一個相當不錯的庫,但這部分是一個不好的例子。我不知道這是否仍然是默認行爲,但作爲(舊)[文章](http://james.newtonking.com/archive/2009/02/20/good-date-times-with-json- net.aspx)解釋了您可以使用[`IsoDateTimeConverter`](http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_Converters_IsoDateTimeConverter.htm)來序列化/從一個(有效的)ISO日期字符串代替。 – 2012-03-15 22:13:57

10

我寫使用DataContractJsonSerializer您自己的JSON序列在System.ServiceModel.Web.dll組件[這是包括在WCF的組分.NET 3.5爲標準組件,以及在.NET 3.5 SP1客戶端配置文件(在.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; 
      } 
     } 
    } 
} 
+1

將其調整爲自己的擴展方法,謝謝:) – 2009-05-02 04:30:47

+0

如何防止DataContractJsonSerializer返回XML而不是JSON? – devlord 2012-05-08 17:26:41

3

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

+7

對於那些有興趣的人,它住在System.ServiceModel.Web – 2009-03-17 08:48:37

5

你也應該盡我ServiceStack JsonSerializer - 這是目前based on the benchmarks of the leading JSON serializers最快的.NET JSON序列化和序列化支持任何類型POCO,DataContracts,列表/字典,接口,繼承,後期綁定對象,包括匿名類型,等等。

基本示例:

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

我輸入「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('\b'); 
        } else if (c == 'f') { 
         s.Append('\f'); 
        } else if (c == 'n') { 
         s.Append('\n'); 
        } else if (c == 'r') { 
         s.Append('\r'); 
        } else if (c == 't') { 
         s.Append('\t'); 
        } 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 ("-.eE".IndexOf(json[lastIndex]) == -1) { 
        break; 
       } 
      } 
      return lastIndex - 1; 
     } 

     protected static void EatWhitespace(char[] json, ref int index) 
     { 
      for (; index < json.Length; index++) { 
       if (" \t\n\r".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 == '\b') { 
        builder.Append("\\b"); 
       } else if (c == '\f') { 
        builder.Append("\\f"); 
       } else if (c == '\n') { 
        builder.Append("\\n"); 
       } else if (c == '\r') { 
        builder.Append("\\r"); 
       } else if (c == '\t') { 
        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); 
     } 
    } 
} 
1

我用System.Web.Helpers.Json編碼和解碼。它解碼爲動態類型,這與javascript的動態數據非常吻合。