Есть ли способ десериализации содержимого JSON в динамический тип C # 4? Было бы неплохо пропустить создание группы классов, чтобы использовать DataContractJsonSerializer
.
Есть ли способ десериализации содержимого JSON в динамический тип C # 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)
params
(это ключевое слово в C #). В дополнение к TryGetMember
вы можете переопределить TryGetIndex
, что дает вам точно такое же поведение, как в JS. Тогда вы можете сделать obj["params"]
или obj["background-color"]
для неловких имен полей.
Это довольно просто с помощью 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
сделайте что-то вроде:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
метода. Если я сделаю метод синхронным, он будет работать как положено. Однако, сделайте метод, async
и я не могу получить dynamic
, я просто получаю object
. Явное приведение ничего не делает, все еще только дает мне 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<dynamic>(str);
Это самый простой способ.
Dictionary<string,object>
. Если я что-то упустил, ваш пример не возвращает динамический объект.
we already know how to get the dictionary and casting it to a dynamic
. Это не должно быть dictionay. Json также имеет списки помимо словаря. А также списки и словари могут быть вложенными. Мой код может обрабатывать все эти ситуации. НО ваш метод не может.
IDynamicMetaObjectProvider
(или использовать, например ExpandoObject
), который может перехватывать свойства и искать их во внутреннем словаре. Это в сочетании с использованием dynamic
позволяет использовать такой код d.code
. Отчасти бессмысленно приводить словарь в динамику.
Простые «строковые данные 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);
myObject["myprop"]
? Я знаю, что это делается во время выполнения, но как myObject["myprop"]
действителен доступ к нему через ?
JsonFx может десериализовать контент JSON в динамические объекты.
Сериализация в / из динамических типов (по умолчанию для .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 Objects. Я использовал объекты раскрытия, потому что я хотел сериализовать динамический обратно в 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;
Вы можете достичь этого с помощью Newtonsoft.Json. Установите Newtonsoft.Json из Nuget и выполните следующие действия:
using Newtonsoft.Json;
dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
Самый простой способ:
Просто включите этот файл 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, чтобы рекурсивно скопировать созданный им словарь для расширения объектов и затем использовать их динамически:
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 не является допустимым именем 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; }
}
Для этого я использовал бы JSON.NET, чтобы выполнить низкоуровневый анализ потока JSON, а затем создать иерархию объектов из экземпляров ExpandoObject
класса.
Я использую как это в моем коде, и он работает нормально
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
Посмотрите на статью, которую я написал на CodeProject, которая точно отвечает на вопрос:
Здесь слишком много места для повторной публикации, и еще меньше смысла, поскольку в этой статье есть вложение с ключом / необходимым исходным файлом.
Другой вариант - «Вставить JSON как классы», чтобы его можно было быстро и легко десериализовать.
Вот лучшее объяснение n piccas ... «Вставить JSON As Classes» в ASP.NET и Web Tools 2012.2 RC
Десериализация в 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());
Смотрите пост для полного примера.
Требуемый объект DynamicJSONObject включен в System.Web.Helpers.dll из пакета веб-страниц ASP.NET, который является частью WebMatrix.
Существует легкая библиотека JSON для C #, которая называется SimpleJson .
Он поддерживает .NET 3.5+, Silverlight и Windows Phone 7.
Он поддерживает динамический для .NET 4.0
Он также может быть установлен как пакет NuGet
Install-Package SimpleJson
Используйте DataSet (C #) с JavaScript. Простая функция для создания потока JSON с вводом DataSet. Создайте содержимое в формате JSON, как (набор данных из нескольких таблиц):
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a: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},{a:58,b:59,c:45}]]')
Тогда используйте:
d[0][0].a // out 1 from table 0 row 0
d[1][1].b // out 59 from table 1 row 1
// Created 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());
Пожалуйста, добавьте ссылку на 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();
}
С 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 address: " + rec.ip);
}
}
Вывод:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
Отказ от ответственности: я автор этой библиотеки.
попробуй так!
Пример JSON:
[{
"id": 140,
"group": 1,
"text": "xxx",
"creation_date": 123456,
"created_by": "xxx@gmail.co",
"tags": ["xxxxx"]
}, {
"id": 141,
"group": 1,
"text": "xxxx",
"creation_date": 123456,
"created_by": "xxx@gmail.com",
"tags": ["xxxxx"]
}]
Код C #:
var jsonString = (File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(),"delete_result.json")));
var objects = JsonConvert.DeserializeObject<dynamic>(jsonString);
foreach(var o in objects)
{
Console.WriteLine($"{o.id.ToString()}");
}