⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 javascriptserializer.cs

📁 AJAX开发工具包
💻 CS
字号:
/*
 * MS	06-04-03	fixed Decimal value, now using double instead
 * MS	06-04-04	added enum as integer instead of returning a class
 * 
 * 
 * 
 */
using System;
using System.Text;
using System.Reflection;

namespace AjaxPro
{
	/// <summary>
	/// Provides methods for serializing .NET objects to Java Script Object Notation (JSON).
	/// </summary>
	public class JavaScriptSerializer
	{
		/// <summary>
		/// Converts a .NET object into a JSON string.
		/// </summary>
		/// <param name="o">The object to convert.</param>
		/// <returns>Returns a JSON string.</returns>
		/// <example>
		/// using System;
		/// using AjaxPro;
		/// 
		/// namespace Demo
		/// {
		///		public class WebForm1 : System.Web.UI.Page
		///		{
		///			private void Page_Load(object sender, System.EventArgs e)
		///			{
		///				DateTime serverTime = DateTime.Now;
		///				string json = JavaScriptSerializer.Serialize(serverTime);
		///				
		///				// json = "new Date(...)";
		///			}
		///		}
		/// }
		/// </example>
		public static string Serialize(object o)
		{
			JavaScriptSerializer js = new JavaScriptSerializer();
			return js.SerializeInternal(o);
		}

		/// <summary>
		/// Converts a string into a JSON string.
		/// </summary>
		/// <param name="s">The string to convert.</param>
		/// <returns>Returns a JSON string.</returns>
		public static string SerializeString(string s)
		{
			JavaScriptSerializer js = new JavaScriptSerializer();
			return js.SerializeInternal(s);
		}

		#region Internal Methods

		internal string SerializeInternal(object o)
		{
			StringBuilder sb = new StringBuilder();

			this.SerializeValue(o, sb);

			return sb.ToString();
		}

		internal void SerializeString(string s, StringBuilder sb)
		{
			sb.Append("\"");
			sb.Append(JavaScriptUtil.QuoteString(s));
			sb.Append("\"");
		}

		internal void SerializeDecimal(Decimal d, StringBuilder sb)
		{
			// this.SerializeValue(Decimal.GetBits(d), sb);

			// The following code is not correct, but while JavaScript cannot
			// handle the decimal value correct we are using double instead.

			this.SerializePrimitive((double)d, sb);
		}

		internal void SerializeBoolean(bool b, StringBuilder sb)
		{
			sb.Append((b ? "true" : "false"));
		}

		internal void SerializePrimitive(object o, StringBuilder sb)
		{
			if(o is char || o is byte || o is sbyte)
			{
				sb.Append(o.ToString());
				return;
			}

			if(o is float && ((float)o) == float.NaN)
			{
				throw new ArgumentException("object must be a valid number (float.NaN)", "number");
			}

			if(o is double && ((double)o) == double.NaN)
			{
				throw new ArgumentException("object must be a valid number (double.NaN)", "number");
			}

			// Shave off trailing zeros and decimal point, if possible
			string s = o.ToString().ToLower().Replace(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, ".");

			if(s.IndexOf('e') < 0 && s.IndexOf('.') > 0)
			{
				while(s.EndsWith("0"))
				{
					s.Substring(0,s.Length-1);
				}
				if (s.EndsWith("."))
				{
					s.Substring(0,s.Length-1);
				}
			}
			
			sb.Append(s);
		}

		internal void SerializeArray(Array a, StringBuilder sb)
		{
			bool b = true;

			sb.Append("[");

			foreach(object o in a)
			{
				if(b){ b = false; }
				else{ sb.Append(","); }

				this.SerializeValue(o, sb);
			}

			sb.Append("]");
		}

		internal void SerializeCustomObject(object o, StringBuilder sb)
		{
			AjaxNonSerializableAttribute[] nsa = (AjaxNonSerializableAttribute[])o.GetType().GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true);

			bool b = false;

			sb.Append('{');
			
			sb.Append("\"__type\":");
			this.SerializeString(o.GetType().AssemblyQualifiedName, sb);

			
			FieldInfo[] fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
			for(int i=0; i<fields.Length; i++)
			{
				FieldInfo fi = fields[i];

				if((nsa.Length > 0 && fi.GetCustomAttributes(typeof(AjaxPropertyAttribute), true).Length > 0) ||
                    (nsa.Length == 0 && fi.GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true).Length == 0))
				{
					if(b){ b = false; }
					else{ sb.Append(','); }

					this.SerializeString(fi.Name, sb);
					sb.Append(':');
					this.SerializeValue(fi.GetValue(o), sb);
				}
			}

			b = false;

			PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.GetProperty | (BindingFlags.Public | BindingFlags.Instance));
			for(int i=0; i<properties.Length; i++)
			{
				PropertyInfo prop = properties[i];

				MethodInfo mi = prop.GetGetMethod();
				if (mi.GetParameters().Length <= 0)
				{
					if((nsa.Length > 0 && mi.GetCustomAttributes(typeof(AjaxPropertyAttribute), true).Length > 0) ||
                        (nsa.Length == 0 && mi.GetCustomAttributes(typeof(AjaxNonSerializableAttribute), true).Length == 0))
					{
						if(b){ b = false; }
						else{ sb.Append(","); }

						this.SerializeString(prop.Name, sb);
						sb.Append(':');
						this.SerializeValue(mi.Invoke(o, null), sb);
					}
				}
			}

			sb.Append('}');
		}

		internal void SerializeValue(object o, StringBuilder sb)
		{
			if(o == null || o is System.DBNull)
			{
				sb.Append("null");
			}
			else if(o is string)
			{
				this.SerializeString((string)o, sb);
			}
			else if(o is char)
			{
				this.SerializeString(o.ToString(), sb);
			}
			else if(o is bool)
			{
				this.SerializeBoolean((bool)o, sb);
			}
#if(NET20)
			//else if (o is Nullable)
			//{

			//}
#endif
            else if (o.GetType().IsPrimitive)
            {
                this.SerializePrimitive(o, sb);
            }
			else if (o.GetType().IsEnum)
			{
				this.SerializePrimitive((int)o, sb);
			}
			else if (o is Guid)
			{
				this.SerializeString(o.ToString(), sb);
			}
			else if (o is Decimal)
			{
				this.SerializeDecimal((Decimal)o, sb);
				// sb.Append(o.ToString());
			}
			else if (o is Exception)
			{
				Exception ex = (Exception)o;

				sb.Append("null; r.error = {\"Message\":");
				this.SerializeString(ex.Message, sb);
				sb.Append(",\"Type\":");
				this.SerializeString(o.GetType().FullName, sb);

				if (AjaxPro.Utility.Settings.DebugEnabled)
				{
					sb.Append(",\"Stack\":");
					this.SerializeString(ex.StackTrace, sb);
					sb.Append(",\"TargetSite\":");
					this.SerializeString(ex.TargetSite.ToString(), sb);
					sb.Append(",\"Source\":");
					this.SerializeString(ex.Source, sb);
				}

				sb.Append("}");
			}
			else
			{
				JavaScriptConverterAttribute[] attr = (JavaScriptConverterAttribute[])o.GetType().GetCustomAttributes(typeof(JavaScriptConverterAttribute), false);
				if (attr.Length > 0)
				{
					sb.Append(attr[0].Converter.Serialize(o));
					return;
				}

				IJavaScriptConverter c = JavaScriptConverter.GetSerializableConverter(o.GetType());
				if (c != null)
				{
					sb.Append(c.Serialize(o));
					return;
				}

				if (o.GetType().IsArray)
				{
					this.SerializeArray((Array)o, sb);
				}
				else
				{
					this.SerializeCustomObject(o, sb);
				}
			}
		}

		#endregion
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -