将JSON反序列化为C#dynamic对象?
有没有办法将JSON内容反序列化成C#4dynamictypes? 为了使用DataContractJsonSerializer,跳过创build一堆类会很好。
如果你很高兴在System.Web.Helpers
程序集上有依赖,那么你可以使用Json
类:
dynamic data = Json.Decode(json);
它包含在MVC框架中,作为.NET 4框架的附加下载 。 如果这有帮助的话,一定要给Vlad一个好消息! 但是,如果您不能假定客户端环境包含此DLL,请继续阅读。
这里提出了一种替代的反序列化方法。 我稍微修改了代码来修复一个错误并适合我的编码风格。 所有你需要的是这个代码和你的项目对System.Web.Extensions
的引用:
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using System.Linq; using System.Text; using System.Web.Script.Serialization; public sealed class DynamicJsonConverter : JavaScriptConverter { public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary == null) throw new ArgumentNullException("dictionary"); return type == typeof(object) ? new DynamicJsonObject(dictionary) : null; } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { throw new NotImplementedException(); } public override IEnumerable<Type> SupportedTypes { get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); } } #region Nested type: DynamicJsonObject private sealed class DynamicJsonObject : DynamicObject { private readonly IDictionary<string, object> _dictionary; public DynamicJsonObject(IDictionary<string, object> dictionary) { if (dictionary == null) throw new ArgumentNullException("dictionary"); _dictionary = dictionary; } public override string ToString() { var sb = new StringBuilder("{"); ToString(sb); return sb.ToString(); } private void ToString(StringBuilder sb) { var firstInDictionary = true; foreach (var pair in _dictionary) { if (!firstInDictionary) sb.Append(","); firstInDictionary = false; var value = pair.Value; var name = pair.Key; if (value is string) { sb.AppendFormat("{0}:\"{1}\"", name, value); } else if (value is IDictionary<string, object>) { new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb); } else if (value is ArrayList) { sb.Append(name + ":["); var firstInArray = true; foreach (var arrayValue in (ArrayList)value) { if (!firstInArray) sb.Append(","); firstInArray = false; if (arrayValue is IDictionary<string, object>) new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb); else if (arrayValue is string) sb.AppendFormat("\"{0}\"", arrayValue); else sb.AppendFormat("{0}", arrayValue); } sb.Append("]"); } else { sb.AppendFormat("{0}:{1}", name, value); } } sb.Append("}"); } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (!_dictionary.TryGetValue(binder.Name, out result)) { // return null to avoid exception. caller can check for null this way... result = null; return true; } result = WrapResultObject(result); return true; } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { if (indexes.Length == 1 && indexes[0] != null) { if (!_dictionary.TryGetValue(indexes[0].ToString(), out result)) { // return null to avoid exception. caller can check for null this way... result = null; return true; } result = WrapResultObject(result); return true; } return base.TryGetIndex(binder, indexes, out result); } private static object WrapResultObject(object result) { var dictionary = result as IDictionary<string, object>; if (dictionary != null) return new DynamicJsonObject(dictionary); var arrayList = result as ArrayList; if (arrayList != null && arrayList.Count > 0) { return arrayList[0] is IDictionary<string, object> ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x))) : new List<object>(arrayList.Cast<object>()); } return result; } } #endregion }
你可以像这样使用它:
string json = ...; var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); dynamic obj = serializer.Deserialize(json, typeof(object));
所以,给一个JSONstring:
{ "Items":[ { "Name":"Apple", "Price":12.3 }, { "Name":"Grape", "Price":3.21 } ], "Date":"21/11/2010" }
以下代码将在运行时工作:
dynamic data = serializer.Deserialize(json, typeof(object)); data.Date; // "21/11/2010" data.Items.Count; // 2 data.Items[0].Name; // "Apple" data.Items[0].Price; // 12.3 (as a decimal) data.Items[1].Name; // "Grape" data.Items[1].Price; // 3.21 (as a decimal)
使用Json.NET非常简单:
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }"); string name = stuff.Name; string address = stuff.Address.City;
还using Newtonsoft.Json.Linq
:
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }"); string name = stuff.Name; string address = stuff.Address.City;
文档: 用dynamic查询JSON
你可以使用System.Web.Helpers.Json来完成 – 它的Decode方法返回一个dynamic对象,你可以随心所欲地遍历它。
它包含在System.Web.Helpers程序集(.NET 4.0)中。
var dynamicObject = Json.Decode(jsonString);
.Net 4.0有一个内置的库来做到这一点:
using System.Web.Script.Serialization; JavaScriptSerializer jss = new JavaScriptSerializer(); var d=jss.Deserialize<dynamic>(str);
这是最简单的方法。
简单的“stringJSON数据”对象没有任何第三方DLL
WebClient client = new WebClient(); string getString = client.DownloadString("https://graph.facebook.com/zuck"); JavaScriptSerializer serializer = new JavaScriptSerializer(); dynamic item = serializer.Deserialize<object>(getString); string name = item["name"]; //note: JavaScriptSerializer in this namespaces //System.Web.Script.Serialization.JavaScriptSerializer
注意:您也可以使用您的自定义对象。
Personel item = serializer.Deserialize<Personel>(getString);
JsonFx可以将json反序列化为dynamic对象。
我制作了使用Expando Objects的DynamicJsonConverter的新版本。 我使用expando对象,因为我想使用Json.net将dynamic序列化回到json。
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using System.Web.Script.Serialization; public static class DynamicJson { public static dynamic Parse(string json) { JavaScriptSerializer jss = new JavaScriptSerializer(); jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() }); dynamic glossaryEntry = jss.Deserialize(json, typeof(object)) as dynamic; return glossaryEntry; } class DynamicJsonConverter : JavaScriptConverter { public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary == null) throw new ArgumentNullException("dictionary"); var result = ToExpando(dictionary); return type == typeof(object) ? result : null; } private static ExpandoObject ToExpando(IDictionary<string, object> dictionary) { var result = new ExpandoObject(); var dic = result as IDictionary<String, object>; foreach (var item in dictionary) { var valueAsDic = item.Value as IDictionary<string, object>; if (valueAsDic != null) { dic.Add(item.Key, ToExpando(valueAsDic)); continue; } var arrayList = item.Value as ArrayList; if (arrayList != null && arrayList.Count > 0) { dic.Add(item.Key, ToExpando(arrayList)); continue; } dic.Add(item.Key, item.Value); } return result; } private static ArrayList ToExpando(ArrayList obj) { ArrayList result = new ArrayList(); foreach (var item in obj) { var valueAsDic = item as IDictionary<string, object>; if (valueAsDic != null) { result.Add(ToExpando(valueAsDic)); continue; } var arrayList = item as ArrayList; if (arrayList != null && arrayList.Count > 0) { result.Add(ToExpando(arrayList)); continue; } result.Add(item); } return result; } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { throw new NotImplementedException(); } public override IEnumerable<Type> SupportedTypes { get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); } } } }
使用Newtonsoft.Json的另一种方法是:
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }"); string color = stuff.color; int value = stuff.value;
最简单的方法是
只包括这个DLL
使用这样的代码
dynamic json = new JDynamic("{a:'abc'}"); //json.a is a string "abc" dynamic json = new JDynamic("{a:3.1416}"); //json.a is 3.1416m dynamic json = new JDynamic("{a:1}"); //json.a is dynamic json = new JDynamic("[1,2,3]"); /json.Length/json.Count is 3 //And you can use json[0]/ json[2] to get the elements dynamic json = new JDynamic("{a:[1,2,3]}"); //json.a.Length /json.a.Count is 3. //And you can use json.a[0]/ json.a[2] to get the elements dynamic json = new JDynamic("[{b:1},{c:1}]"); //json.Length/json.Count is 2. //And you can use the json[0].b/json[1].c to get the num.
您可以扩展JavaScriptSerializer以recursion地将其创build的字典复制到一个或多个对象,然后dynamic使用它们:
static class JavaScriptSerializerExtensions { public static dynamic DeserializeDynamic(this JavaScriptSerializer serializer, string value) { var dictionary = serializer.Deserialize<IDictionary<string, object>>(value); return GetExpando(dictionary); } private static ExpandoObject GetExpando(IDictionary<string, object> dictionary) { var expando = (IDictionary<string, object>)new ExpandoObject(); foreach (var item in dictionary) { var innerDictionary = item.Value as IDictionary<string, object>; if (innerDictionary != null) { expando.Add(item.Key, GetExpando(innerDictionary)); } else { expando.Add(item.Key, item.Value); } } return (ExpandoObject)expando; } }
然后你只需要为你定义扩展名的命名空间使用using语句(可以考虑在System.Web.Script.Serialization中定义它们…另一个窍门是不使用命名空间,那么你不需要使用声明),你可以像这样消耗它们:
var serializer = new JavaScriptSerializer(); var value = serializer.DeserializeDynamic("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }"); var name = (string)value.Name; // Jon Smith var age = (int)value.Age; // 42 var address = value.Address; var city = (string)address.City; // New York var state = (string)address.State; // NY
我在我的代码中使用这样的,它工作正常
using System.Web.Script.Serialization; JavaScriptSerializer oJS = new JavaScriptSerializer(); RootObject oRootObject = new RootObject(); oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
为此,我将使用JSON.NET对JSONstream进行低级parsing,然后用ExpandoObject
类的实例构build对象层次结构。
JSON.NET中的反序列化可以使用包含在该库中的JObject
类来dynamic化。 我的JSONstring表示这些类:
public class Foo { public int Age {get;set;} public Bar Bar {get;set;} } public class Bar { public DateTime BDay {get;set;} }
现在我们反序列化string而不引用上面的类:
var dyn = JsonConvert.DeserializeObject<JObject>(jsonAsFooString); JProperty propAge = dyn.Properties().FirstOrDefault(i=>i.Name == "Age"); if(propAge != null) { int age = int.Parse(propAge.Value.ToString()); Console.WriteLine("age=" + age); } //or as a one-liner: int myage = int.Parse(dyn.Properties().First(i=>i.Name == "Age").Value.ToString());
或者如果你想深入一些:
var propBar = dyn.Properties().FirstOrDefault(i=>i.Name == "Bar"); if(propBar != null) { JObject o = (JObject)propBar.First(); var propBDay = o.Properties().FirstOrDefault (i => i.Name=="BDay"); if(propBDay != null) { DateTime bday = DateTime.Parse(propBDay.Value.ToString()); Console.WriteLine("birthday=" + bday.ToString("MM/dd/yyyy")); } } //or as a one-liner: DateTime mybday = DateTime.Parse(((JObject)dyn.Properties().First(i=>i.Name == "Bar").First()).Properties().First(i=>i.Name == "BDay").Value.ToString());
看完整的例子后。
你可以使用using Newtonsoft.Json
var jRoot = JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
是我从调用核心事件得到的响应。
它可能有点晚,以帮助你,但你想要的对象DynamicJSONObject包括在ASP.NET Web Pages包,这是WebMatrix的一部分System.Web.Helpers.dll。
有一个C#的轻量级json库叫SimpleJson,可以在http://simplejson.codeplex.comfindhttps://github.com/facebook-csharp-sdk/simple-json
它支持.net 3.5+,silverlight和windows phone 7。
支持.net 4.0的dynamic
也可以作为nuget包安装
Install-Package SimpleJson
使用DataSet(C#)用javascript简单的函数来创buildjsonstream与数据集input创buildjson像(多表数据集)[[{a:1,b:2,c:3},{a:3,b:5,c :6}],[{A:23,b:45,C:35},{一个:58,b:59,C:45}]]
只是客户端使用eval为例
var d = eval('[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35 },{一个:58,b:59,C:45}]]')
然后使用
d [0] [0] .a //从表0第0行的out 1
d [1] [1] .b //从表1的第1行中取出59
//create by Behnam Mohammadi And Saeed Ahmadian public string jsonMini(DataSet ds) { int t=0, r=0, c=0; string stream = "["; for (t = 0; t < ds.Tables.Count; t++) { stream += "["; for (r = 0; r < ds.Tables[t].Rows.Count; r++) { stream += "{"; for (c = 0; c < ds.Tables[t].Columns.Count; c++) { stream += ds.Tables[t].Columns[c].ToString() + ":'" + ds.Tables[t].Rows[r][c].ToString() + "',"; } if(c>0) stream = stream.Substring(0, stream.Length - 1); stream += "},"; } if(r>0) stream = stream.Substring(0, stream.Length - 1); stream += "],"; } if(t>0) stream = stream.Substring(0, stream.Length - 1); stream += "];"; return stream; }
获取ExpandoObject:
using Newtonsoft.Json; using Newtonsoft.Json.Converters; Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
尝试这个 –
var units = new { Name = "Phone", Color= "White" }; var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
看看我在CodeProject上写的文章,其中一个恰好回答了这个问题:
dynamictypes与JSON.NET
有太多的重新发布这里所有的东西,甚至更less的点,因为这篇文章有关键/必需的源文件的附件。
我使用: http : //json2csharp.com/获取代表Json对象的类。
input:
{ "name":"John", "age":31, "city":"New York", "Childs":[ { "name":"Jim", "age":11 }, { "name":"Tim", "age":9 } ] }
输出:
public class Child { public string name { get; set; } public int age { get; set; } } public class Person { public string name { get; set; } public int age { get; set; } public string city { get; set; } public List<Child> Childs { get; set; } }
之后,我使用Newtonsoft.Json填充类:
using Newtonsoft.Json; namespace GitRepositoryCreator.Common { class JObjects { public static string Get(object p_object) { return JsonConvert.SerializeObject(p_object); } internal static T Get<T>(string p_object) { return JsonConvert.DeserializeObject<T>(p_object); } } }
你可以这样称呼它:
Person jsonClass = JObjects.Get<Person>(stringJson); string stringJson = JObjects.Get(jsonClass);
PS:
如果你的jsonvariables名不是有效的C#名字(名字以$
开头),你可以修改这样的:
public class Exception { [JsonProperty(PropertyName = "$id")] public string id { get; set; } public object innerException { get; set; } public string message { get; set; } public string typeName { get; set; } public string typeKey { get; set; } public int errorCode { get; set; } public int eventId { get; set; } }