using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
namespace fastJSON
{
public class JSON
{
public readonly static JSON Instance = new JSON();
private JSON()
{
}
public string ToJSON(object obj)
{
return new JSONSerializer().ConvertToJSON(obj);
}
public object ToObject(string json)
{
Dictionary<string, object> ht = (new JsonParser().JsonDecode(json) as Dictionary<string, object>) ;
if (ht == null)
return null;
return ParseDictionary(ht);
}
#region [ PROPERTY GET SET CACHE ]
private object FastCreateInstance(Type objtype)
{
return Activator.CreateInstance(objtype);
}
SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>();
private Type GetTypeFromCache(string typename)
{
if (_typecache.ContainsKey(typename))
return _typecache[typename];
else
{
Type t = Type.GetType(typename);
_typecache.Add(typename, t);
return t;
}
}
SafeDictionary<string, PropertyInfo> _propertycache = new SafeDictionary<string, PropertyInfo>();
private PropertyInfo getproperty(Type type, string propertyname)
{
if (propertyname == "$type")
return null;
string n = string.Concat(type.Name, propertyname);
if (_propertycache.ContainsKey(n))
{
return _propertycache[n];
}
else
{
PropertyInfo[] pr = type.GetProperties();
foreach (PropertyInfo p in pr)
{
string nn = string.Concat(type.Name, p.Name);
if (_propertycache.ContainsKey(nn) == false)
_propertycache.Add(nn, p);
}
return _propertycache[n];
}
}
private delegate void GenericSetter(object target, object value);
private static GenericSetter CreateSetMethod(PropertyInfo propertyInfo)
{
MethodInfo setMethod = propertyInfo.GetSetMethod();
if (setMethod == null)
return null;
Type[] arguments = new Type[2];
arguments[0] = arguments[1] = typeof(object);
DynamicMethod setter = new DynamicMethod(
String.Concat("_Set", propertyInfo.Name, "_"),
typeof(void), arguments, propertyInfo.DeclaringType);
ILGenerator il = setter.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
il.Emit(OpCodes.Ldarg_1);
if (propertyInfo.PropertyType.IsClass)
il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
else
il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
il.EmitCall(OpCodes.Callvirt, setMethod, null);
il.Emit(OpCodes.Ret);
return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter));
}
internal delegate object GenericGetter(object target);
private static GenericGetter CreateGetMethod(PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod();
if (getMethod == null)
return null;
Type[] arguments = new Type[1];
arguments[0] = typeof(object);
DynamicMethod getter = new DynamicMethod(
String.Concat("_Get", propertyInfo.Name, "_"),
typeof(object), arguments, propertyInfo.DeclaringType);
ILGenerator il = getter.GetILGenerator();
il.DeclareLocal(typeof(object));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
il.EmitCall(OpCodes.Callvirt, getMethod, null);
if (!propertyInfo.PropertyType.IsClass)
il.Emit(OpCodes.Box, propertyInfo.PropertyType);
il.Emit(OpCodes.Ret);
return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter));
}
SafeDictionary<Type, List<Getters>> _getterscache = new SafeDictionary<Type, List<Getters>>();
internal List<Getters> GetGetters(Type type)
{
if(_getterscache.ContainsKey(type))
return _getterscache[type];
else
{
PropertyInfo[] props = type.GetProperties(BindingFlags.Public| BindingFlags.Instance);
List<Getters> getters = new List<Getters>();
foreach(PropertyInfo p in props)
{
GenericGetter g = CreateGetMethod(p);
if(g!=null)
{
Getters gg = new Getters();
gg.Name = p.Name;
gg.Getter = g;
getters.Add(gg);
}
}
_getterscache.Add(type,getters);
return getters;
}
}
SafeDictionary<PropertyInfo, GenericSetter> _settercache = new SafeDictionary<PropertyInfo, GenericSetter>();
private GenericSetter GetSetter(PropertyInfo prop)
{
if (_settercache.ContainsKey(prop))
return _settercache[prop];
else
{
GenericSetter s = CreateSetMethod(prop);
_settercache.Add(prop, s);
return s;
}
}
#endregion
private object ParseDictionary(Dictionary<string, object> d)
{
string tn = d["$type"].ToString();
Type type = GetTypeFromCache(tn);
object o = FastCreateInstance(type);
foreach (string name in d.Keys)
{
PropertyInfo pi = getproperty(type, name);
if (pi != null && pi.CanWrite)
{
object v = d[name];
if (v != null)
{
object oset = null;
GenericSetter setter;
Type pt = pi.PropertyType;
object dic = pt.GetInterface("IDictionary");
if (pt.IsGenericType && pt.IsValueType == false && dic==null)
{
IList col = (IList)FastCreateInstance(pt);
// create an array of objects
foreach (object ob in (v as ArrayList))
{
if(ob is IDictionary)
col.Add(ParseDictionary(ob as Dictionary<string, object>));
else
col.Add(ob);
}
oset = col;
}
else if (pt == typeof(byte[]))
{
oset = Convert.FromBase64String((v as string));
}
else if (pt.IsArray && pt.IsValueType == false)
{
ArrayList col = new ArrayList();
Type bt = pt.GetElementType();
// create an array of objects
foreach (object ob in (v as ArrayList))
{
if(ob is IDictionary)
col.Add(ParseDictionary((ob as Dictionary<string, object>)));
else
col.Add(ob);
}
oset = col.ToArray(bt);
}
else if (pt == typeof(Guid) || pt == typeof(Guid?))
oset = new Guid(v.ToString());
else if (pt == typeof(DataSet))
oset = CreateDataset((v as Dictionary<string, object>));
else if (pt == typeof(Hashtable))
oset = CreateDictionary((v as ArrayList),pt);
else if (dic!=null)
oset = CreateDictionary((v as ArrayList),pt);
else
oset = ChangeType(v, pt);
setter = GetSetter(pi);
setter(o, oset);
}
}
}
return o;
}
private object CreateDictionary(ArrayList reader, Type pt)
{
IDictionary col = (FastCreateInstance(pt) as IDictionary);
Type[] types = col.GetType().GetGenericArguments();
foreach (object o in reader)
{
Dictionary<string, object> values = (o as Dictionary<string, object>);
object key;
object val;
if(values["k"] is Dictionary<string,object>)
key = ParseDictionary((values["k"] as Dictionary<string,object>));
else
key = ChangeType(values["k"] , types[0]);
if (values["v"] is Dictionary<string, object>)
val = ParseDictionary((values["v"] as Dictionary<string, object>));
else
val = ChangeType(values["v"] , types[1]);
col.Add(key , val);
}
return col;
}
SafeDictionary<Type,Type> _changetype = new SafeDictionary<Type, Type>();
private object ChangeType(object value, Type conversionType)
{
if ( conversionType.IsGenericType &&
conversionType.GetGenericTypeDefinition( ).Equals( typeof( Nullable<> ) ) ) {
if(_changetype.ContainsKey(conversionType))
conversionType = _changetype[conversionType];
else
{
Type t = conversionType.GetGenericArguments()[0];
_changetype.Add(conversionType,t);
conversionType=t;
}
}
return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
}
private Hashtable CreateHashtable(ArrayList reader)
{
Hashtable ht = new Hashtable();
foreach (object o in reader)
{
Dictionary<string, object> values = (o as Dictionary<string, object>);
ht.Add(
ParseDictionary((values["k"] as Dictionary<string,object>)),
ParseDictionary((values["v"] as Dictionary<string,object>))
);
}
return ht;
}
private DataSet CreateDataset(Dictionary<string, object> reader)
{
DataSet ds = new DataSet();
// read dataset schema here
DatasetSchema ms = ParseDictionary(((reader["$schema"] as Dictionary<string,object>))) as DatasetSchema;
ds.DataSetName = ms.Name;
for (int i = 0; i < ms.Info.Count; i+=3)
{
if(ds.Tables.Contains(ms.Info[i])== false)
ds.Tables.Add(ms.Info[i]);
ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i+1],Type.GetType(ms.Info[i+2]));
}
ds.EnforceConstraints=false;
ds.BeginInit();
foreach (string key in reader.Keys)
{
if (key == "$type" || key == "$schema")
continue;
object tb = reader[key];
if (tb != null && tb.GetType() == typeof(ArrayList))
{
ArrayList rows = (tb as ArrayList);
DataTable dt = ds.Tables[key];
dt.BeginInit();
dt.BeginLoadData();
foreach (Dictionary<string,object> row in rows)
{
ArrayList ar = new ArrayList(row.Values);
dt.Rows.Add(ar.ToArray());
}
dt.EndLoadData();
dt.EndInit();
}
}
ds.EndInit();
return ds;
}
}
}