Есть ли способ десериализации содержимого JSON в динамический тип C # 4? Было бы неплохо пропустить создание группы classов, чтобы использовать DataContractJsonSerializer.
Если вы счастливы иметь зависимость от сборки System.Web.Helpers , вы можете использовать class Json :
dynamic data = Json.Decode(json);
Он включен в структуру MVC в качестве дополнительной загрузки в среду .NET 4. Обязательно дайте Владу вздохнуть, если это будет полезно! Однако, если вы не можете предположить, что клиентская среда включает эту 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 dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary == null) throw new ArgumentNullException("dictionary"); return type == typeof(object) ? new DynamicJsonObject(dictionary) : null; } public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { throw new NotImplementedException(); } public override IEnumerable SupportedTypes { get { return new ReadOnlyCollection(new List(new[] { typeof(object) })); } } #region Nested type: DynamicJsonObject private sealed class DynamicJsonObject : DynamicObject { private readonly IDictionary _dictionary; public DynamicJsonObject(IDictionary 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) { new DynamicJsonObject((IDictionary)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) new DynamicJsonObject((IDictionary)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; if (dictionary != null) return new DynamicJsonObject(dictionary); var arrayList = result as ArrayList; if (arrayList != null && arrayList.Count > 0) { return arrayList[0] is IDictionary ? new List
Вы можете использовать его следующим образом:
string json = ...; var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); dynamic obj = serializer.Deserialize(json, typeof(object));
Вы можете сделать это с помощью System.Web.Helpers.Json – его метод Decode возвращает динамический объект, который вы можете перемещать по своему усмотрению.
Он включен в сборку 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(str);
Это самый простой способ.
Простые «строковые json-данные» для объекта без какой-либо сторонней dll
WebClient client = new WebClient(); string getString = client.DownloadString("https://graph.facebook.com/zuck"); JavaScriptSerializer serializer = new JavaScriptSerializer(); dynamic item = serializer.Deserialize(getString); string name = item["name"]; //note: JavaScriptSerializer in this namespaces //System.Web.Script.Serialization.JavaScriptSerializer
Примечание. Вы также можете использовать свой пользовательский объект.
Сериализация в / из динамических типов (по умолчанию для .NET 4.0):
var reader = new JsonReader(); var writer = new JsonWriter(); string input = @"{ ""foo"": true, ""array"": [ 42, false, ""Hello!"", null ] }"; dynamic output = reader.Read(input); Console.WriteLine(output.array[0]); // 42 string json = writer.Write(output); Console.WriteLine(json); // {"foo":true,"array":[42,false,"Hello!",null]}
Я сделал новую версию DynamicJsonConverter, которая использует объекты Expando. Я использовал объекты expando, потому что я хотел Сериализовать динамику обратно в json, используя Json.net.
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 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 dictionary) { var result = new ExpandoObject(); var dic = result as IDictionary; foreach (var item in dictionary) { var valueAsDic = item.Value as IDictionary; 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; 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 Serialize(object obj, JavaScriptSerializer serializer) { throw new NotImplementedException(); } public override IEnumerable SupportedTypes { get { return new ReadOnlyCollection(new List(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, чтобы рекурсивно скопировать словарь, который он создал для объектов expando, а затем использовать их динамически:
static class JavaScriptSerializerExtensions { public static dynamic DeserializeDynamic(this JavaScriptSerializer serializer, string value) { var dictionary = serializer.Deserialize>(value); return GetExpando(dictionary); } private static ExpandoObject GetExpando(IDictionary dictionary) { var expando = (IDictionary)new ExpandoObject(); foreach (var item in dictionary) { var innerDictionary = item.Value as IDictionary; 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
Для этого я бы использовал JSON.NET для анализа синтаксиса JSON на низком уровне, а затем создавал иерархию объектов из экземпляров classа ExpandoObject .
Я использую это в своем коде, и он отлично работает
using System.Web.Script.Serialization; JavaScriptSerializer oJS = new JavaScriptSerializer(); RootObject oRootObject = new RootObject(); oRootObject = oJS.Deserialize(Your JSon String);
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 Childs { get; set; } }
После этого я использую Newtonsoft.Json для заполнения classа:
using Newtonsoft.Json; namespace GitRepositoryCreator.Common { class JObjects { public static string Get(object p_object) { return JsonConvert.SerializeObject(p_object); } internal static T Get(string p_object) { return JsonConvert.DeserializeObject(p_object); } } }
Вы можете назвать это так:
Person jsonClass = JObjects.Get(stringJson); string stringJson = JObjects.Get(jsonClass);
PS:
Если имя переменной json не является допустимым именем 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; } }
Вы можете использовать using Newtonsoft.Json
var jRoot = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data – это мой ответ от вызова основного события.
Вероятно, вам немного поздно помочь вам, но объект, который вы хотите, DynamicJSONObject включен в System.Web.Helpers.dll из пакета веб-страниц ASP.NET, который является частью WebMatrix.
Он поддерживает .net 3.5+, silverlight и Windows Phone 7.
Поддерживает динамику для .net 4.0
Также может быть установлен как пакет nuget
Install-Package SimpleJson
использовать DataSet (C #) С помощью простой функции javascript для создания streamа json с вводом DataSet создайте json like (dataset с несколькими таблицами) [[{a: 1, b: 2, c: 3}, {a: 3, b: 5, c : 6}], [{а: 23, B: 45, с: 35}, {а: 58, B: 59, с: 45}]]
только клиентская сторона использует eval, например
//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; }
Дессериализация в JSON.NET может быть динамической, используя class JObject , который включен в эту библиотеку. Моя строка JSON представляет эти classы:
public class Foo { public int Age {get;set;} public Bar Bar {get;set;} } public class Bar { public DateTime BDay {get;set;} }
Теперь мы десериализуем строку БЕЗ ссылок на вышеуказанные classы:
var dyn = JsonConvert.DeserializeObject(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());
См. Сообщение для полного примера.
Посмотрите на статью, которую я написал в CodeProject, которая точно отвечает на вопрос:
Динамические типы с JSON.NET
Существует слишком много для повторной публикации всего этого, и даже меньше, поскольку эта статья имеет вложение с ключом / требуемым исходным файлом.
Чтобы получить ExpandoObject:
using Newtonsoft.Json; using Newtonsoft.Json.Converters; Container container = JsonConvert.Deserialize(jsonAsString, new ExpandoObjectConverter());
попробуй это –
var units = new { Name = "Phone", Color= "White" }; var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
Другой вариант – «Вставить JSON в качестве classов», чтобы его можно было десериализовать быстро и просто.
Просто скопируйте весь JSON
В VS: нажмите «Редактирование»> «Вставить»> «Вставить» JSON в качестве classов