Есть ли способ десериализации содержимого JSON в динамический тип С# 4? Было бы неплохо пропустить создание группы классов, чтобы использовать DataContractJsonSerializer.
Если вы счастливы иметь зависимость от сборки System.Web.Helpers
, вы можете использовать класс 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<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));
Итак, учитывая строку JSON:
{
"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;
Документация: Запрос JSON с динамическим
stuff
?
Вы можете сделать это с помощью 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<dynamic>(str);
Это самый простой способ.
Dictionary<string,object>
. Если я что-то упустил, ваш пример не возвращает динамический объект.
Простые "строковые данные json" для объекта без какой-либо сторонней 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 в динамических объектах.
https://github.com/jsonfx/jsonfx
Сериализация в/из динамических типов (по умолчанию для.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<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, чтобы рекурсивно скопировать словарь, который он создал для объектов expando, и затем использовать их динамически:
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 Newtonsoft.Json
var jRoot =
JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
- это мой ответ от вызова основного события.
Я использую: http://json2csharp.com/, чтобы получить класс, представляющий объект Json.
Входные данные:
{
"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:
Если имя переменной json не является допустимым именем С# (имя начинается с $
), вы можете исправить это следующим образом:
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 System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
Для этого я бы использовал JSON.NET для синтаксического анализа низкого уровня потока JSON, а затем создавал иерархию объектов из экземпляров класса ExpandoObject
.
Deserializing в JSON.NET может быть динамическим, используя класс JObject
, который включен в эту библиотеку. Моя строка JSON представляет эти классы:
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
Теперь мы десериализуем строку БЕЗ ссылок на вышеуказанные классы:
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());
Для получения полного примера см. post.
использовать DataSet (С#) с помощью javascript простая функция для создания потока json с вводом DataSet создать json like (набор данных с несколькими таблицами) [[{А: 1, б: 2, с: 3}, {а: 3, б: 5, с: 6}], [{а: 23, B: 45, с: 35}, {а: 58, B: 59, с: 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, с: 45}]] ')
затем используйте
d [0] [0].a//out 1 из таблицы 0 строка 0
d [1] [1].b//out 59 из таблицы 1 строка 1
//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;
}
Посмотрите на статью, которую я написал в CodeProject, которая точно отвечает на вопрос:
Существует слишком много для повторной публикации всего этого, и даже меньше, поскольку в этой статье есть вложение с ключом/требуемым исходным файлом.
Provide context for links A link to a potential solution is always welcome, but please add context around the link so your fellow users will have some idea what it is and why it's there
Существует легкая библиотека json для С#, называемая SimpleJson, которую можно найти в http://simplejson.codeplex.com https://github.com/facebook-csharp-sdk/simple-json
Он поддерживает .net 3.5+, silverlight и Windows 7 телефона.
Поддерживает динамику для .net 4.0
Также может быть установлен как пакет nuget
Install-Package SimpleJson
Возможно, вам немного поздно помочь вам, но объект, который вы хотите, DynamicJSONObject включен в System.Web.Helpers.dll из пакета веб-страниц ASP.NET, который является частью WebMatrix.
попробуйте это -
var units = new { Name = "Phone", Color= "White" };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
Чтобы получить объект ExpandoObject:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
Добавьте ссылку System.Web.Extensions и добавьте это пространство имен using System.Web.Script.Serialization;
наверху
public static void EasyJson()
{
var jsonText = @"{
""some_number"": 108.541,
""date_time"": ""2011-04-13T15:34:09Z"",
""serial_number"": ""SN1234""
}";
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<dynamic>(jsonText);
Console.WriteLine(dict["some_number"]);
Console.ReadLine();
}
Добавьте ссылку System.Web.Extensions и добавьте это пространство имен using System.Web.Script.Serialization;
наверху
public static void ComplexJson()
{
var jsonText = @"{
""some_number"": 108.541,
""date_time"": ""2011-04-13T15:34:09Z"",
""serial_number"": ""SN1234"",
""more_data"": {
""field1"": 1.0,
""field2"": ""hello""
}
}";
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<dynamic>(jsonText);
Console.WriteLine(dict["some_number"]);
Console.WriteLine(dict["more_data"]["field2"]);
Console.ReadLine();
}
Другой вариант - "Вставить JSON в качестве классов", чтобы его можно было десериализовать быстро и просто.
Вот лучшее объяснение n piccas... https://blogs.msdn.microsoft.com/webdev/2012/12/18/paste-json-as-classes-in-asp-net-and-web-tools- 2012-2-гс/
С Cinchoo ETL - библиотека с открытым исходным кодом, доступная для синтаксического анализа json в динамическом объекте
string json = @"{
""key1"": [
{
""action"": ""open"",
""timestamp"": ""2018-09-05 20:46:00"",
""url"": null,
""ip"": ""66.102.6.98""
}
]
}";
using (var p = ChoJSONReader.LoadText(json)
.WithJSONPath("$.*")
)
{
foreach (var rec in p)
{
Console.WriteLine("action: " + rec.action);
Console.WriteLine("timestamp: " + rec.timestamp);
Console.WriteLine("url: " + rec.url);
Console.WriteLine("ip: " + rec.ip);
}
}
Выход:
action: open
timestamp: 2018-09-05 20:46:00
url: http://www.google.com
ip: 66.102.6.98
Отказ от ответственности: я являюсь автором этой библиотеки.
используйте код ниже, который приведен в изображении ниже.