JavaScriptDeserializer.cs
上传用户:szgaoree
上传日期:2009-01-05
资源大小:74k
文件大小:8k
源码类别:

Ajax

开发平台:

C#

  1. /*
  2.  * MS 06-04-11 fixed array deserializer
  3.  * fixed ArrayList deserializer, using Int64 if JavaScriptNumber, Boolean if JavaScriptBoolean
  4.  * MS 06-04-12 fixed type char (BUG: will return """ instead of ""
  5.  * MS 06-04-13 fixed type char when char is empty JSON string
  6.  * 
  7.  * 
  8.  */
  9. using System;
  10. using System.Text;
  11. using System.Reflection;
  12. using System.Collections;
  13. namespace AjaxPro
  14. {
  15. /// <summary>
  16. /// Provides methods for deserializing .NET objects from a Java Script Object Notation (JSON) string to an .NET object.
  17. /// </summary>
  18. public class JavaScriptDeserializer
  19. {
  20. /// <summary>
  21. /// Converts an JSON string into an NET object.
  22. /// </summary>
  23. /// <param name="json">The JSON string representation.</param>
  24. /// <param name="type">The type to convert the string to.</param>
  25. /// <returns>Returns a .NET object.</returns>
  26. /// <example>
  27. /// using System;
  28. /// using AjaxPro;
  29. /// 
  30. /// namespace Demo
  31. /// {
  32. /// public class WebForm1 : System.Web.UI.Page
  33. /// {
  34. /// private void Page_Load(object sender, System.EventArgs e)
  35. /// {
  36. /// string json = "[1,2,3,4,5,6]";
  37. ///
  38. /// object o = JavaScriptDeserializer.Deserialize(json, typeof(int[]);
  39. ///
  40. /// if(o != null)
  41. /// {
  42. /// foreach(int i in (int[])o)
  43. /// {
  44. /// Response.Write(i.ToString());
  45. /// }
  46. /// }
  47. /// }
  48. /// }
  49. /// }
  50. /// </example>
  51. public static object Deserialize(string json, Type type)
  52. {
  53. JSONParser p = new JSONParser();
  54. IJavaScriptObject o = p.GetJSONObject(json);
  55. return JavaScriptDeserializer.DeserializeInternal(o, type);
  56. }
  57. /// <summary>
  58. /// Converts an IJavaScriptObject into an NET object.
  59. /// </summary>
  60. /// <param name="o">The IJavaScriptObject object to convert.</param>
  61. /// <param name="type">The type to convert the object to.</param>
  62. /// <returns>Returns a .NET object.</returns>
  63. public static object Deserialize(IJavaScriptObject o, Type type)
  64. {
  65. return DeserializeInternal(o, type);
  66. }
  67. #region Internal Methods
  68. internal static Decimal DeserializeDecimal(JavaScriptArray a, Type type)
  69. {
  70. if (a != null && a.Count != 4)
  71. throw new NotSupportedException();
  72. int[] i = (int[])JavaScriptDeserializer.DeserializeInternal(a, typeof(int[]));
  73. return new Decimal(i);
  74. }
  75. internal static object DeserializePrimitive(IJavaScriptObject n, Type type)
  76. {
  77. if (!type.IsPrimitive)
  78. throw new NotSupportedException();
  79. string s = n.ToString();
  80. // TODO: return the default value for this primitive data type
  81. s = s.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
  82. if (type == typeof(short))
  83. return short.Parse(s);
  84. else if (type == typeof(int))
  85. return int.Parse(s);
  86. else if (type == typeof(long))
  87. return long.Parse(s);
  88. else if (type == typeof(ushort))
  89. return ushort.Parse(s);
  90. else if (type == typeof(uint))
  91. return uint.Parse(s);
  92. else if (type == typeof(ulong))
  93. return ulong.Parse(s);
  94. else if (type == typeof(byte))
  95. return byte.Parse(s);
  96. else if (type == typeof(sbyte))
  97. return sbyte.Parse(s);
  98. else if (type == typeof(char))
  99. {
  100. //s = s.Substring(1, s.Length - 2);
  101. //s = s.Replace(""", "");
  102. if (s.Length == 0)
  103. return '';
  104. return s[0];
  105. }
  106. else if (type == typeof(float))
  107. return float.Parse(s);
  108. else if (type == typeof(double))
  109. return double.Parse(s);
  110. throw new NotImplementedException("This primitive data type '" + type.FullName + "' is not implemented.");
  111. }
  112. internal static object DeserializeArray(JavaScriptArray list, Type type)
  113. {
  114. Type t = Type.GetType(type.AssemblyQualifiedName.Replace("[]", "")); // TODO: Not very good implementation.
  115. Array a = Array.CreateInstance(t, list.Count);
  116. for (int i = 0; i < list.Count; i++)
  117. {
  118. object v = JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)list[i], t);
  119. a.SetValue(v, i);
  120. }
  121. return a;
  122. }
  123. internal static object DeserializeCustomObject(JavaScriptObject o, Type type)
  124. {
  125. object c = Activator.CreateInstance(type);
  126. // TODO: is this a security problem?
  127. // if(o.GetType().GetCustomAttributes(typeof(AjaxClassAttribute), true).Length == 0)
  128. // throw new System.Security.SecurityException("Could not create class '" + type.FullName + "' because of missing AjaxClass attribute.");
  129. MemberInfo[] members = type.GetMembers(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
  130. foreach (MemberInfo memberInfo in members)
  131. {
  132. if (memberInfo.MemberType == MemberTypes.Field)
  133. {
  134. if (o.Contains(memberInfo.Name))
  135. {
  136. FieldInfo fieldInfo = (FieldInfo)memberInfo;
  137. fieldInfo.SetValue(c, JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)o[fieldInfo.Name], fieldInfo.FieldType));
  138. }
  139. }
  140. else if (memberInfo.MemberType == MemberTypes.Property)
  141. {
  142. if (o.Contains(memberInfo.Name))
  143. {
  144. PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
  145. if (propertyInfo.CanWrite)
  146. propertyInfo.SetValue(c, JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)o[propertyInfo.Name], propertyInfo.PropertyType), new object[0]);
  147. }
  148. }
  149. }
  150. return c;
  151. }
  152. internal static object DeserializeInternal(IJavaScriptObject o, Type type)
  153. {
  154. if ((o is JavaScriptObject) && ((JavaScriptObject)o).Contains("__type"))
  155. {
  156. Type t = Type.GetType(((JavaScriptObject)o)["__type"].ToString());
  157. if (type == null || type.IsAssignableFrom(t))
  158. {
  159. type = t;
  160. }
  161. }
  162. if (o == null)
  163. {
  164. return null;
  165. }
  166. else if (type.IsAssignableFrom(typeof(string)))
  167. {
  168. if (o is JavaScriptNumber)
  169. return DeserializeInternal(o, typeof(Int64));
  170. else if (o is JavaScriptBoolean)
  171. return DeserializeInternal(o, typeof(bool));
  172. return o.ToString();
  173. }
  174. else if (type == typeof(bool) && o is JavaScriptBoolean)
  175. {
  176. return (bool)((JavaScriptBoolean)o);
  177. }
  178. else if (type.IsPrimitive)
  179. {
  180. return JavaScriptDeserializer.DeserializePrimitive(o, type);
  181. }
  182. else if (type == typeof(Guid))
  183. {
  184. return new Guid(o.ToString());
  185. }
  186. else if (type == typeof(System.Decimal) && o is JavaScriptNumber)
  187. {
  188. string s = ((JavaScriptNumber)o).Value;
  189. // TODO: return the default value for this primitive data type
  190. s = s.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);
  191. Decimal d = Decimal.Parse(s,
  192. System.Globalization.NumberStyles.Currency |
  193. System.Globalization.NumberStyles.AllowExponent);
  194. return d;
  195. }
  196. // else if(type == typeof(System.Decimal) && o is JavaScriptArray)
  197. // {
  198. // return JavaScriptDeserializer.DeserializeDecimal((JavaScriptArray)o, type);
  199. // }
  200. else if (typeof(IJavaScriptObject).IsAssignableFrom(type))
  201. {
  202. return o;
  203. }
  204. #if(NET20)
  205. else if (type.IsGenericType && type.GetGenericArguments().Length > 0)
  206. {
  207. Type[] types = type.GetGenericArguments();
  208. if (typeof(System.Collections.Generic.List<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && o is JavaScriptArray)
  209. {
  210. object g = Activator.CreateInstance(type);
  211. JavaScriptArray a = (JavaScriptArray)o;
  212. System.Collections.IList list = (System.Collections.IList)g;
  213. foreach (IJavaScriptObject item in a)
  214. list.Add(DeserializeInternal(item, types[0]));
  215. return list;
  216. }
  217. }
  218. #endif
  219. else
  220. {
  221. if (o is JavaScriptArray && (type.IsArray || type == typeof(System.Array)))
  222. {
  223. return JavaScriptDeserializer.DeserializeArray((JavaScriptArray)o, type);
  224. }
  225. JavaScriptConverterAttribute[] attr = (JavaScriptConverterAttribute[])type.GetCustomAttributes(typeof(JavaScriptConverterAttribute), false);
  226. if (attr.Length > 0)
  227. {
  228. return attr[0].Converter.Deserialize(o, type);
  229. }
  230. IJavaScriptConverter c = JavaScriptConverter.GetDeserializableConverter(type);
  231. if (c != null)
  232. {
  233. return c.Deserialize(o, type);
  234. }
  235. if (o is JavaScriptObject)
  236. {
  237. return JavaScriptDeserializer.DeserializeCustomObject((JavaScriptObject)o, type);
  238. }
  239. }
  240. throw new NotImplementedException("The object of type '" + o.GetType().FullName + "' could not converted to type '" + type + "'.");
  241. }
  242. #endregion
  243. }
  244. }