javascriptdeserializer.cs

来自「AJAX开发工具包」· CS 代码 · 共 287 行

CS
287
字号
/*
 * MS	06-04-11	fixed array deserializer
 *					fixed ArrayList deserializer, using Int64 if JavaScriptNumber, Boolean if JavaScriptBoolean
 * MS	06-04-12	fixed type char (BUG: will return "\"" instead of ""
 * MS	06-04-13	fixed type char when char is empty JSON string
 * 
 * 
 */
using System;
using System.Text;
using System.Reflection;
using System.Collections;

namespace AjaxPro
{
	/// <summary>
	/// Provides methods for deserializing .NET objects from a Java Script Object Notation (JSON) string to an .NET object.
	/// </summary>
	public class JavaScriptDeserializer
	{
		/// <summary>
		/// Converts an JSON string into an NET object.
		/// </summary>
		/// <param name="json">The JSON string representation.</param>
		/// <param name="type">The type to convert the string to.</param>
		/// <returns>Returns a .NET object.</returns>
		/// <example>
		/// using System;
		/// using AjaxPro;
		/// 
		/// namespace Demo
		/// {
		///		public class WebForm1 : System.Web.UI.Page
		///		{
		///			private void Page_Load(object sender, System.EventArgs e)
		///			{
		///				string json = "[1,2,3,4,5,6]";
		///				
		///				object o = JavaScriptDeserializer.Deserialize(json, typeof(int[]);
		///				
		///				if(o != null)
		///				{
		///					foreach(int i in (int[])o)
		///					{
		///						Response.Write(i.ToString());
		///					}
		///				}
		///			}
		///		}
		/// }
		/// </example>
		public static object Deserialize(string json, Type type)
		{
			JSONParser p = new JSONParser();
			IJavaScriptObject o = p.GetJSONObject(json);

			return JavaScriptDeserializer.DeserializeInternal(o, type);
		}

		/// <summary>
		/// Converts an IJavaScriptObject into an NET object.
		/// </summary>
		/// <param name="o">The IJavaScriptObject object to convert.</param>
		/// <param name="type">The type to convert the object to.</param>
		/// <returns>Returns a .NET object.</returns>
		public static object Deserialize(IJavaScriptObject o, Type type)
		{
			return DeserializeInternal(o, type);
		}

		#region Internal Methods

		internal static Decimal DeserializeDecimal(JavaScriptArray a, Type type)
		{
			if (a != null && a.Count != 4)
				throw new NotSupportedException();

			int[] i = (int[])JavaScriptDeserializer.DeserializeInternal(a, typeof(int[]));

			return new Decimal(i);
		}

		internal static object DeserializePrimitive(IJavaScriptObject n, Type type)
		{
			if (!type.IsPrimitive)
				throw new NotSupportedException();

			string s = n.ToString();

			// TODO: return the default value for this primitive data type
			s = s.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);

			if (type == typeof(short))
				return short.Parse(s);
			else if (type == typeof(int))
				return int.Parse(s);
			else if (type == typeof(long))
				return long.Parse(s);
			else if (type == typeof(ushort))
				return ushort.Parse(s);
			else if (type == typeof(uint))
				return uint.Parse(s);
			else if (type == typeof(ulong))
				return ulong.Parse(s);
			else if (type == typeof(byte))
				return byte.Parse(s);
			else if (type == typeof(sbyte))
				return sbyte.Parse(s);
			else if (type == typeof(char))
			{
				//s = s.Substring(1, s.Length - 2);
				//s = s.Replace("\"", "");

				if (s.Length == 0)
					return '\0';

				return s[0];
			}
			else if (type == typeof(float))
				return float.Parse(s);
			else if (type == typeof(double))
				return double.Parse(s);

			throw new NotImplementedException("This primitive data type '" + type.FullName + "' is not implemented.");
		}

		internal static object DeserializeArray(JavaScriptArray list, Type type)
		{
			Type t = Type.GetType(type.AssemblyQualifiedName.Replace("[]", ""));		// TODO: Not very good implementation.
			Array a = Array.CreateInstance(t, list.Count);

			for (int i = 0; i < list.Count; i++)
			{
				object v = JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)list[i], t);
				a.SetValue(v, i);
			}

			return a;
		}

		internal static object DeserializeCustomObject(JavaScriptObject o, Type type)
		{
			object c = Activator.CreateInstance(type);

			// TODO: is this a security problem?
			//			if(o.GetType().GetCustomAttributes(typeof(AjaxClassAttribute), true).Length == 0)
			//				throw new System.Security.SecurityException("Could not create class '" + type.FullName + "' because of missing AjaxClass attribute.");

			MemberInfo[] members = type.GetMembers(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
			foreach (MemberInfo memberInfo in members)
			{
				if (memberInfo.MemberType == MemberTypes.Field)
				{
					if (o.Contains(memberInfo.Name))
					{
						FieldInfo fieldInfo = (FieldInfo)memberInfo;

						fieldInfo.SetValue(c, JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)o[fieldInfo.Name], fieldInfo.FieldType));
					}
				}
				else if (memberInfo.MemberType == MemberTypes.Property)
				{
					if (o.Contains(memberInfo.Name))
					{
						PropertyInfo propertyInfo = (PropertyInfo)memberInfo;

						if (propertyInfo.CanWrite)
							propertyInfo.SetValue(c, JavaScriptDeserializer.DeserializeInternal((IJavaScriptObject)o[propertyInfo.Name], propertyInfo.PropertyType), new object[0]);
					}
				}
			}

			return c;
		}

		internal static object DeserializeInternal(IJavaScriptObject o, Type type)
		{
			if ((o is JavaScriptObject) && ((JavaScriptObject)o).Contains("__type"))
			{
				Type t = Type.GetType(((JavaScriptObject)o)["__type"].ToString());

				if (type == null || type.IsAssignableFrom(t))
				{
					type = t;
				}
			}

			if (o == null)
			{
				return null;
			}
			else if (type.IsAssignableFrom(typeof(string)))
			{
				if (o is JavaScriptNumber)
					return DeserializeInternal(o, typeof(Int64));
				else if (o is JavaScriptBoolean)
					return DeserializeInternal(o, typeof(bool));

				return o.ToString();
			}
			else if (type == typeof(bool) && o is JavaScriptBoolean)
			{
				return (bool)((JavaScriptBoolean)o);
			}
			else if (type.IsPrimitive)
			{
				return JavaScriptDeserializer.DeserializePrimitive(o, type);
			}
			else if (type == typeof(Guid))
			{
				return new Guid(o.ToString());
			}
			else if (type == typeof(System.Decimal) && o is JavaScriptNumber)
			{
				string s = ((JavaScriptNumber)o).Value;

				// TODO: return the default value for this primitive data type
				s = s.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator);

				Decimal d = Decimal.Parse(s,
					System.Globalization.NumberStyles.Currency |
					System.Globalization.NumberStyles.AllowExponent);

				return d;
			}
			//			else if(type == typeof(System.Decimal) && o is JavaScriptArray)
			//			{
			//				return JavaScriptDeserializer.DeserializeDecimal((JavaScriptArray)o, type);
			//			}
			else if (typeof(IJavaScriptObject).IsAssignableFrom(type))
			{
				return o;
			}
#if(NET20)
			else if (type.IsGenericType && type.GetGenericArguments().Length > 0)
			{
				Type[] types = type.GetGenericArguments();


				if (typeof(System.Collections.Generic.List<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && o is JavaScriptArray)
				{
					object g = Activator.CreateInstance(type);
					JavaScriptArray a = (JavaScriptArray)o;

					System.Collections.IList list = (System.Collections.IList)g;

					foreach (IJavaScriptObject item in a)
						list.Add(DeserializeInternal(item, types[0]));

					return list;
				}
			}
#endif
			else
			{
				if (o is JavaScriptArray && (type.IsArray || type == typeof(System.Array)))
				{
					return JavaScriptDeserializer.DeserializeArray((JavaScriptArray)o, type);
				}

				JavaScriptConverterAttribute[] attr = (JavaScriptConverterAttribute[])type.GetCustomAttributes(typeof(JavaScriptConverterAttribute), false);
				if (attr.Length > 0)
				{
					return attr[0].Converter.Deserialize(o, type);
				}

				IJavaScriptConverter c = JavaScriptConverter.GetDeserializableConverter(type);
				if (c != null)
				{
					return c.Deserialize(o, type);
				}

				if (o is JavaScriptObject)
				{
					return JavaScriptDeserializer.DeserializeCustomObject((JavaScriptObject)o, type);
				}
			}

			throw new NotImplementedException("The object of type '" + o.GetType().FullName + "' could not converted to type '" + type + "'.");
		}

		#endregion
	}
}


⌨️ 快捷键说明

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