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 + -
显示快捷键?