Czy istnieje sposób na deserializację treści JSON na typ dynamiczny C # 4? Byłoby miło pominąć tworzenie grupy zajęć w celu korzystania z DataContractJsonSerializer
.
Czy istnieje sposób na deserializację treści JSON na typ dynamiczny C # 4? Byłoby miło pominąć tworzenie grupy zajęć w celu korzystania z DataContractJsonSerializer
.
Odpowiedzi:
Jeśli chcesz być zależny od System.Web.Helpers
zestawu, możesz użyć Json
klasy:
dynamic data = Json.Decode(json);
Jest dołączony do frameworka MVC jako dodatkowe pobranie do frameworku .NET 4. Pamiętaj, aby dać Vladowi głos, jeśli to pomoże! Jeśli jednak nie możesz założyć, że środowisko klienta zawiera tę bibliotekę DLL, czytaj dalej.
Sugerowane jest tutaj alternatywne podejście do deserializacji . Lekko zmodyfikowałem kod, aby naprawić błąd i pasował do mojego stylu kodowania. Wszystko czego potrzebujesz to ten kod i odniesienie do System.Web.Extensions
twojego projektu:
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
}
Możesz użyć tego w następujący sposób:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
Biorąc pod uwagę ciąg JSON:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
Następujący kod będzie działał w czasie wykonywania:
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
(które jest słowem kluczowym w C #). Oprócz tego TryGetMember
możesz zastąpić TryGetIndex
, co daje dokładnie takie samo zachowanie jak w JS. Następnie możesz zrobić obj["params"]
lub obj["background-color"]
dla niezręcznych nazw pól.
Korzystanie z Json.NET jest dość proste :
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Również 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;
Dokumentacja: Zapytanie JSON z dynamiką
stuff
zrobić coś takiego:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
metody. Jeśli utworzę metodę synchroniczną, będzie działać zgodnie z oczekiwaniami. Jednak stwórz metodę async
i nie mogę dostać dynamic
, po prostu dostaję object
. Jawne rzucanie nic nie robi, wciąż daje mi tylko object
. Czy ktoś jeszcze tego doświadcza?
Możesz to zrobić za pomocą System.Web.Helpers.Json - jego metoda dekodowania zwraca obiekt dynamiczny, który możesz przemierzać w dowolny sposób.
Jest on zawarty w zestawie System.Web.Helpers (.NET 4.0).
var dynamicObject = Json.Decode(jsonString);
.NET 4.0 ma wbudowaną bibliotekę, aby to zrobić:
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
To jest najprostszy sposób.
Dictionary<string,object>
. O ile mi czegoś nie brakuje, twój przykład nie zwraca obiektu dynamicznego.
we already know how to get the dictionary and casting it to a dynamic
. To nie musi być dykcja. Json ma również listy oprócz słownika. Można także zagnieżdżać listy i słowniki. Mój kod może obsłużyć wszystkie te sytuacje. ALE twoja metoda NIE może.
IDynamicMetaObjectProvider
(lub użycie np. ExpandoObject
), który jest w stanie przechwytywać właściwości i wyszukiwać je w wewnętrznym słowniku. To w połączeniu z użyciem dynamic
pozwala na użycie takiego kodu d.code
. Nie ma sensu przesyłać słownika do dynamiki.
Prosty „ciąg danych JSON” do sprzeciwu bez pliku DLL innej firmy:
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
Uwaga: Możesz również użyć własnego obiektu.
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
? Wiem, że odbywa się to w środowisku wykonawczym, ale jak dostęp do niego myObject["myprop"]
jest prawidłowy?
JsonFx może przekształcić zawartość JSON w postaci szeregowej na obiekty dynamiczne.
Serializacja do / z typów dynamicznych (domyślnie dla .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]}
Stworzyłem nową wersję DynamicJsonConverter, która wykorzystuje Expando Objects. Użyłem obiektów expando, ponieważ chciałem serializować dynamikę z powrotem do JSON przy użyciu 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) })); }
}
}
}
Innym sposobem jest użycie Newtonsoft.Json :
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
Możesz to osiągnąć za pomocą Newtonsoft.Json. Zainstaluj Newtonsoft.Json z Nuget i:
using Newtonsoft.Json;
dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
Najprostszym sposobem jest:
Wystarczy dołączyć ten plik DLL .
Użyj następującego kodu:
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.
Możesz rozszerzyć JavaScriptSerializer, aby rekurencyjnie kopiować utworzony słownik do rozwijania obiektów, a następnie używać ich dynamicznie:
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;
}
}
Następnie musisz mieć instrukcję using dla przestrzeni nazw, w której zdefiniowałeś rozszerzenie (rozważ zdefiniowanie ich w System.Web.Script.Serialization ... inną sztuczką jest nie używanie przestrzeni nazw, wtedy nie potrzebujesz użycia oświadczenie w ogóle) i możesz je spożywać w następujący sposób:
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
Możesz użyć using Newtonsoft.Json
var jRoot =
JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
to moja odpowiedź otrzymana od wywołania zdarzenia podstawowego.
Korzystam z http://json2csharp.com/, aby uzyskać klasę reprezentującą obiekt JSON.
Wejście:
{
"name":"John",
"age":31,
"city":"New York",
"Childs":[
{
"name":"Jim",
"age":11
},
{
"name":"Tim",
"age":9
}
]
}
Wynik:
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; }
}
Następnie używam Newtonsoft.Json do wypełnienia klasy:
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);
}
}
}
Możesz to tak nazwać:
Person jsonClass = JObjects.Get<Person>(stringJson);
string stringJson = JObjects.Get(jsonClass);
PS:
Jeśli nazwa zmiennej JSON nie jest prawidłową nazwą C # (nazwa zaczyna się od $
), możesz to naprawić w następujący sposób:
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; }
}
W tym celu użyłbym JSON.NET do parsowania niskiego poziomu strumienia JSON, a następnie zbudowałbym hierarchię obiektów na podstawie instancji ExpandoObject
klasy.
Używam tego w moim kodzie i działa dobrze
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
Spójrz na artykuł, który napisałem na CodeProject, taki, który dokładnie odpowiada na pytanie:
Jest o wiele za dużo na ponowne opublikowanie tego wszystkiego tutaj, a tym bardziej, że ten artykuł ma załącznik z kluczem / wymaganym plikiem źródłowym.
Inną opcją jest „Wklej JSON jako klasy”, aby można było szybko i łatwo dokonać deserializacji.
Oto lepsze wyjaśnienie n piccas ... „Wklej JSON jako klasy” w ASP.NET i Web Tools 2012.2 RC
Deserializacja w JSON.NET może być dynamiczna przy użyciu JObject
klasy zawartej w tej bibliotece. Mój ciąg JSON reprezentuje następujące klasy:
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
Teraz deserializujemy ciąg BEZ odwoływania się do powyższych klas:
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());
Lub jeśli chcesz zejść głębiej:
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());
Zobacz post dla kompletnego przykładu.
Obiekt, który chcesz DynamicJSONObject, jest zawarty w System.Web.Helpers.dll z pakietu stron sieci Web ASP.NET, który jest częścią WebMatrix.
Istnieje lekka biblioteka JSON dla języka C # o nazwie SimpleJson .
Obsługuje .NET 3.5+, Silverlight i Windows Phone 7.
Obsługuje dynamikę dla .NET 4.0
Może być również zainstalowany jako pakiet NuGet
Install-Package SimpleJson
Użyj DataSet (C #) z JavaScript. Prosta funkcja do tworzenia strumienia JSON z wejściem DataSet. Utwórz zawartość JSON, np. (Zestaw danych z wieloma tabelami):
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]
Po stronie klienta, użyj eval. Na przykład,
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}]]')
Następnie użyj:
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;
}
Aby uzyskać obiekt ExpandoObject:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
Dodaj odniesienie do System.Web.Extensions i dodaj tę przestrzeń nazw using System.Web.Script.Serialization;
u góry:
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();
}
Dodaj odniesienie do System.Web.Extensions i dodaj tę przestrzeń nazw using System.Web.Script.Serialization;
u góry:
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();
}
Z Cinchoo ETL - biblioteką open source dostępną do parsowania JSON w obiekt dynamiczny:
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);
}
}
Wynik:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
Oświadczenie: Jestem autorem tej biblioteki.
spróbuj w ten sposób!
Przykład 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"]
}]
Kod 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()}");
}