当json.js遇见dynamic.net烂尾篇
由于最近较忙,上一篇的坑估计要慢慢填了。感觉写文章介绍要比写程序还累啊。先看看测试程序,能够了解api支持哪些功能:
static void Main(string[] args)
{
//wrapper对象
dynamic data = DJson.Wrap(new
{
name = "Jane",
male = false,
age = 24,
dob = DateTime.Now,
friend = new { name = "Jesse", male = true, age = 32, dob = DateTime.Now },
mobile = new object[] { new[] { 86 }, 13888888888 },
});
Console.WriteLine(data.Stringfy());
//数组
data = new DJsonArray();
data[0] = new { name = "小朋盂 1号" };
data[1] = new { name = "小朋盂 2号" };
data[2] = new { name = "小朋盂 3号" };
Console.WriteLine(data.Stringfy());
//反序列化
var json = data.Stringfy();
dynamic obj = DJson.Parse(json);
//修改反序列化后的数据
obj[1] = new { name = "mike", age = 21, dob = DateTime.Now };
Console.WriteLine(obj.Stringfy());
//实际应用,将twitter statues反序列化
json = System.IO.File.ReadAllText("e:/twitter.js");
dynamic statuses = DJson.Parse(json);
for (int i = 0; i < statuses.Length; i++)
{
var status = statuses[i];
Console.WriteLine(" id: {0}\nname: {1}\nfrom: {2}\ntext: {3}\n", status.user.id, status.user.name, status.user.location, status.text);
}
Console.ReadKey();
}
twitter文件请在这里下载
先放上代码,其实很简单,以后再慢慢分析
public class DJson : DynamicObject
{
protected Dictionary<string, object> _expando = new Dictionary<string, object>();
public override string ToString()
{
return this.Stringify();
}
public IEnumerable<string> Keys { get { return _expando.Keys; } }
public object this[string key] { get { return _expando[key]; } set { _expando[key] = value; } }
public DJson() { }
public static DJson Wrap(object obj)
{
if (!(obj is string) && (obj is IEnumerable) && !(obj is Dictionary<string, object>))
{
var array = new DJsonArray();
int i = 0;
foreach (object v in obj as IEnumerable)
array[i++] = DJson.Wrap(v);
return array;
}
else
{
var dj = new DJson();
if (obj is Dictionary<string, object>)
{
foreach (var kv in obj as Dictionary<string, object>)
{
if (kv.Value == null)
dj[kv.Key] = (object)null;
else if (IsPrimitive(kv.Value.GetType()))
dj[kv.Key] = kv.Value;
else
dj[kv.Key] = DJson.Wrap(kv.Value);
}
}
else
{
var t = obj.GetType();
if (IsPrimitive(t))
throw new ArgumentException();
foreach (var p in t.GetProperties())
{
var v = p.GetValue(obj, null);
if (IsPrimitive(p.PropertyType))
dj[p.Name] = v;
else
dj[p.Name] = DJson.Wrap(v);
}
}
return dj;
}
}
public static DJson Parse(string json)
{
var obj = (new JavaScriptSerializer()).DeserializeObject(json);
return DJson.Wrap(obj);
}
public string Stringify()
{
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new DJsonConverter() });
if (this is DJsonArray)
return serializer.Serialize((this as DJsonArray).ToArray());
return serializer.Serialize(this);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_expando.TryGetValue(binder.Name, out result))
return true;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (!(value is string) && (value is IEnumerable))
_expando[binder.Name] = new DJsonArray(value as IEnumerable);
else
_expando[binder.Name] = value;
return true;
}
internal static bool IsPrimitive(Type type)
{
return type.FullName.StartsWith("System.") && !type.FullName.StartsWith("System.Collection");
}
}
public class DJsonArray : DJson
{
Dictionary<int, object> _array = new Dictionary<int, object>();
public object this[int index] { get { return _array[index]; } set { _array[index] = value; } }
public int Length { get { return _array.Keys.Count; } }
public DJsonArray() { }
public DJsonArray(IEnumerable array)
{
int i = 0;
foreach (var obj in array)
this[i++] = obj;
}
public object[] ToArray()
{
return _array.Values.ToArray();
}
public DJson ToObject()
{
var dj = new DJson();
foreach (string key in _expando.Keys)
dj[key] = _expando[key];
foreach (int key in _array.Keys)
dj[key.ToString()] = _array[key];
return dj;
}
}
internal class DJsonConverter : JavaScriptConverter
{
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var dj = (DJson)obj;
var result = new Dictionary<string, object>();
foreach (string key in dj.Keys)
{
if (dj[key] is DJsonArray)
result[key] = (dj[key] as DJsonArray).ToArray();
else
result[key] = dj[key];
}
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>(new Type[] { typeof(DJson), typeof(DJsonArray) }); }
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
}
Newton的json库最近好像做了相同的事情,开始支持dynamic了
http://james.newtonking.com/archive/2011/01/03/json-net-4-0-release-1-net-4-and-windows-phone-support.aspx