JavaScriptDeserializer.cs
上传用户:szgaoree
上传日期:2009-01-05
资源大小:74k
文件大小:8k
- /*
- * 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 ' ';
- 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
- }
- }