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

Ajax

开发平台:

C#

  1. /*
  2.  * MS 06-04-03 fixed Decimal value, now using double instead
  3.  * MS 06-04-04 added enum as integer instead of returning a class
  4.  * 
  5.  * 
  6.  * 
  7.  */
  8. using System;
  9. using System.Text;
  10. using System.Reflection;
  11. namespace AjaxPro
  12. {
  13. /// <summary>
  14. /// Provides methods for serializing .NET objects to Java Script Object Notation (JSON).
  15. /// </summary>
  16. public class JavaScriptSerializer
  17. {
  18. /// <summary>
  19. /// Converts a .NET object into a JSON string.
  20. /// </summary>
  21. /// <param name="o">The object to convert.</param>
  22. /// <returns>Returns a JSON string.</returns>
  23. /// <example>
  24. /// using System;
  25. /// using AjaxPro;
  26. /// 
  27. /// namespace Demo
  28. /// {
  29. /// public class WebForm1 : System.Web.UI.Page
  30. /// {
  31. /// private void Page_Load(object sender, System.EventArgs e)
  32. /// {
  33. /// DateTime serverTime = DateTime.Now;
  34. /// string json = JavaScriptSerializer.Serialize(serverTime);
  35. ///
  36. /// // json = "new Date(...)";
  37. /// }
  38. /// }
  39. /// }
  40. /// </example>
  41. public static string Serialize(object o)
  42. {
  43. JavaScriptSerializer js = new JavaScriptSerializer();
  44. return js.SerializeInternal(o);
  45. }
  46. /// <summary>
  47. /// Converts a string into a JSON string.
  48. /// </summary>
  49. /// <param name="s">The string to convert.</param>
  50. /// <returns>Returns a JSON string.</returns>
  51. public static string SerializeString(string s)
  52. {
  53. JavaScriptSerializer js = new JavaScriptSerializer();
  54. return js.SerializeInternal(s);
  55. }
  56. #region Internal Methods
  57. internal string SerializeInternal(object o)
  58. {
  59. StringBuilder sb = new StringBuilder();
  60. this.SerializeValue(o, sb);
  61. return sb.ToString();
  62. }
  63. internal void SerializeString(string s, StringBuilder sb)
  64. {
  65. sb.Append(""");
  66. sb.Append(JavaScriptUtil.QuoteString(s));
  67. sb.Append(""");
  68. }
  69. internal void SerializeDecimal(Decimal d, StringBuilder sb)
  70. {
  71. // this.SerializeValue(Decimal.GetBits(d), sb);
  72. // The following code is not correct, but while JavaScript cannot
  73. // handle the decimal value correct we are using double instead.
  74. this.SerializePrimitive((double)d, sb);
  75. }
  76. internal void SerializeBoolean(bool b, StringBuilder sb)
  77. {
  78. sb.Append((b ? "true" : "false"));
  79. }
  80. internal void SerializePrimitive(object o, StringBuilder sb)
  81. {
  82. if(o is char || o is byte || o is sbyte)
  83. {
  84. sb.Append(o.ToString());
  85. return;
  86. }
  87. if(o is float && ((float)o) == float.NaN)
  88. {
  89. throw new ArgumentException("object must be a valid number (float.NaN)", "number");
  90. }
  91. if(o is double && ((double)o) == double.NaN)
  92. {
  93. throw new ArgumentException("object must be a valid number (double.NaN)", "number");
  94. }
  95. // Shave off trailing zeros and decimal point, if possible
  96. string s = o.ToString().ToLower().Replace(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, ".");
  97. if(s.IndexOf('e') < 0 && s.IndexOf('.') > 0)
  98. {
  99. while(s.EndsWith("0"))
  100. {
  101. s.Substring(0,s.Length-1);
  102. }
  103. if (s.EndsWith("."))
  104. {
  105. s.Substring(0,s.Length-1);
  106. }
  107. }
  108. sb.Append(s);
  109. }
  110. internal void SerializeArray(Array a, StringBuilder sb)
  111. {
  112. bool b = true;
  113. sb.Append("[");
  114. foreach(object o in a)
  115. {
  116. if(b){ b = false; }
  117. else{ sb.Append(","); }
  118. this.SerializeValue(o, sb);
  119. }
  120. sb.Append("]");
  121. }
  122. internal void SerializeCustomObject(object o, StringBuilder sb)
  123. {
  124. AjaxNonSerializableAttribute[] nsa = (AjaxNonSerializableAttribute[])o.GetType().GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true);
  125. bool b = false;
  126. sb.Append('{');
  127. sb.Append(""__type":");
  128. this.SerializeString(o.GetType().AssemblyQualifiedName, sb);
  129. FieldInfo[] fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
  130. for(int i=0; i<fields.Length; i++)
  131. {
  132. FieldInfo fi = fields[i];
  133. if((nsa.Length > 0 && fi.GetCustomAttributes(typeof(AjaxPropertyAttribute), true).Length > 0) ||
  134.                     (nsa.Length == 0 && fi.GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true).Length == 0))
  135. {
  136. if(b){ b = false; }
  137. else{ sb.Append(','); }
  138. this.SerializeString(fi.Name, sb);
  139. sb.Append(':');
  140. this.SerializeValue(fi.GetValue(o), sb);
  141. }
  142. }
  143. b = false;
  144. PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.GetProperty | (BindingFlags.Public | BindingFlags.Instance));
  145. for(int i=0; i<properties.Length; i++)
  146. {
  147. PropertyInfo prop = properties[i];
  148. MethodInfo mi = prop.GetGetMethod();
  149. if (mi.GetParameters().Length <= 0)
  150. {
  151. if((nsa.Length > 0 && mi.GetCustomAttributes(typeof(AjaxPropertyAttribute), true).Length > 0) ||
  152.                         (nsa.Length == 0 && mi.GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true).Length == 0))
  153. {
  154. if(b){ b = false; }
  155. else{ sb.Append(","); }
  156. this.SerializeString(prop.Name, sb);
  157. sb.Append(':');
  158. this.SerializeValue(mi.Invoke(o, null), sb);
  159. }
  160. }
  161. }
  162. sb.Append('}');
  163. }
  164. internal void SerializeValue(object o, StringBuilder sb)
  165. {
  166. if(o == null || o is System.DBNull)
  167. {
  168. sb.Append("null");
  169. }
  170. else if(o is string)
  171. {
  172. this.SerializeString((string)o, sb);
  173. }
  174. else if(o is char)
  175. {
  176. this.SerializeString(o.ToString(), sb);
  177. }
  178. else if(o is bool)
  179. {
  180. this.SerializeBoolean((bool)o, sb);
  181. }
  182. #if(NET20)
  183. //else if (o is Nullable)
  184. //{
  185. //}
  186. #endif
  187.             else if (o.GetType().IsPrimitive)
  188.             {
  189.                 this.SerializePrimitive(o, sb);
  190.             }
  191. else if (o.GetType().IsEnum)
  192. {
  193. this.SerializePrimitive((int)o, sb);
  194. }
  195. else if (o is Guid)
  196. {
  197. this.SerializeString(o.ToString(), sb);
  198. }
  199. else if (o is Decimal)
  200. {
  201. this.SerializeDecimal((Decimal)o, sb);
  202. // sb.Append(o.ToString());
  203. }
  204. else if (o is Exception)
  205. {
  206. Exception ex = (Exception)o;
  207. sb.Append("null; r.error = {"Message":");
  208. this.SerializeString(ex.Message, sb);
  209. sb.Append(","Type":");
  210. this.SerializeString(o.GetType().FullName, sb);
  211. if (AjaxPro.Utility.Settings.DebugEnabled)
  212. {
  213. sb.Append(","Stack":");
  214. this.SerializeString(ex.StackTrace, sb);
  215. sb.Append(","TargetSite":");
  216. this.SerializeString(ex.TargetSite.ToString(), sb);
  217. sb.Append(","Source":");
  218. this.SerializeString(ex.Source, sb);
  219. }
  220. sb.Append("}");
  221. }
  222. else
  223. {
  224. JavaScriptConverterAttribute[] attr = (JavaScriptConverterAttribute[])o.GetType().GetCustomAttributes(typeof(JavaScriptConverterAttribute), false);
  225. if (attr.Length > 0)
  226. {
  227. sb.Append(attr[0].Converter.Serialize(o));
  228. return;
  229. }
  230. IJavaScriptConverter c = JavaScriptConverter.GetSerializableConverter(o.GetType());
  231. if (c != null)
  232. {
  233. sb.Append(c.Serialize(o));
  234. return;
  235. }
  236. if (o.GetType().IsArray)
  237. {
  238. this.SerializeArray((Array)o, sb);
  239. }
  240. else
  241. {
  242. this.SerializeCustomObject(o, sb);
  243. }
  244. }
  245. }
  246. #endregion
  247. }
  248. }