Gibt es eine Möglichkeit, JSON-Inhalte in einen dynamischen C # 4-Typ zu deserialisieren? Es wäre schön, das Erstellen einer Reihe von Klassen zu überspringen, um die zu verwenden DataContractJsonSerializer
.
Gibt es eine Möglichkeit, JSON-Inhalte in einen dynamischen C # 4-Typ zu deserialisieren? Es wäre schön, das Erstellen einer Reihe von Klassen zu überspringen, um die zu verwenden DataContractJsonSerializer
.
Antworten:
Wenn Sie froh sind, eine Abhängigkeit von der System.Web.Helpers
Assembly zu haben, können Sie die Json
Klasse verwenden:
dynamic data = Json.Decode(json);
Es ist im MVC-Framework als zusätzlicher Download zum .NET 4-Framework enthalten. Geben Sie Vlad eine positive Bewertung, wenn dies hilfreich ist! Wenn Sie jedoch nicht davon ausgehen können, dass die Clientumgebung diese DLL enthält, lesen Sie weiter.
Ein alternativer Deserialisation Ansatz wird vorgeschlagen , hier . Ich habe den Code leicht geändert, um einen Fehler zu beheben und meinem Codierungsstil zu entsprechen. Sie benötigen lediglich diesen Code und einen Verweis auf System.Web.Extensions
Ihr Projekt:
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
}
Sie können es so verwenden:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
Also, gegeben eine JSON-Zeichenfolge:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
Der folgende Code funktioniert zur Laufzeit:
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
(der ein Schlüsselwort in C # ist). Außerdem TryGetMember
können Sie überschreiben TryGetIndex
, wodurch Sie genau das gleiche Verhalten wie in JS erhalten. Dann können Sie obj["params"]
oder obj["background-color"]
für umständliche Feldnamen.
Mit Json.NET ist das ganz einfach :
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Auch 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;
Dokumentation: Abfrage von JSON mit Dynamic
stuff
machen Sie etwas wie:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
Methode eingegrenzt. Wenn ich die Methode synchronisiere, funktioniert sie wie erwartet. Allerdings mache die Methode async
und ich kann keine bekommen dynamic
, ich bekomme nur eine object
. Explizites Casting macht nichts, gibt mir immer noch nur eine object
. Erlebt das noch jemand?
Sie können dies mit System.Web.Helpers.Json tun Decode-Methode gibt ein dynamisches Objekt zurück, das Sie durchlaufen können.
Es ist in der Assembly System.Web.Helpers (.NET 4.0) enthalten.
var dynamicObject = Json.Decode(jsonString);
.NET 4.0 verfügt über eine integrierte Bibliothek, um dies zu tun:
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
Dies ist der einfachste Weg.
Dictionary<string,object>
. Sofern mir nichts fehlt, gibt Ihr Beispiel kein dynamisches Objekt zurück.
we already know how to get the dictionary and casting it to a dynamic
. Es muss kein Wörterbuch sein. Json hat neben dem Wörterbuch auch Listen. Außerdem können Listen und Wörterbücher verschachtelt werden. Mein Code könnte all diese Situationen bewältigen. ABER Ihre Methode kann NICHT.
IDynamicMetaObjectProvider
(oder zu verwenden ExpandoObject
), die in der Lage sind, Eigenschaften abzufangen und in einem internen Wörterbuch nachzuschlagen. Dies in Kombination mit der Verwendung von dynamic
ermöglicht die Verwendung von Code d.code
. Es ist irgendwie sinnlos, ein Wörterbuch in eine Dynamik umzuwandeln.
Einfache "String-JSON-Daten" zum Objektieren ohne DLL-Datei eines Drittanbieters:
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
Hinweis: Sie können auch Ihr benutzerdefiniertes Objekt verwenden.
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
? Ich weiß, dass es zur Laufzeit gemacht wird, aber wie ist der Zugriff darauf myObject["myprop"]
gültig?
JsonFx kann JSON-Inhalte in dynamische Objekte deserialisieren.
Serialisieren zu / von dynamischen Typen (Standard für .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]}
Ich habe eine neue Version des DynamicJsonConverter erstellt, die Expando-Objekte verwendet. Ich habe expando-Objekte verwendet, weil ich die Dynamik mithilfe von Json.NET wieder in JSON serialisieren wollte.
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) })); }
}
}
}
Eine andere Möglichkeit, Newtonsoft.Json zu verwenden :
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
Sie können dies mit Hilfe von Newtonsoft.Json erreichen. Installieren Sie Newtonsoft.Json von Nuget und:
using Newtonsoft.Json;
dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
Der einfachste Weg ist:
Fügen Sie einfach diese DLL-Datei hinzu .
Verwenden Sie den Code wie folgt:
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.
Sie können den JavaScriptSerializer erweitern, um das erstellte Wörterbuch rekursiv zu kopieren, um Objekte zu erweitern, und sie dann dynamisch zu verwenden:
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;
}
}
Dann brauchen Sie nur noch eine using-Anweisung für den Namespace, in dem Sie die Erweiterung definiert haben (definieren Sie sie einfach in System.Web.Script.Serialization ... ein weiterer Trick besteht darin, keinen Namespace zu verwenden, dann brauchen Sie die using nicht Aussage überhaupt) und Sie können sie so konsumieren:
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
Sie können verwenden using Newtonsoft.Json
var jRoot =
JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
ist meine Antwort vom Aufrufen des Kernereignisses.
Ich verwende http://json2csharp.com/ , um eine Klasse zu erhalten, die das JSON-Objekt darstellt.
Eingang:
{
"name":"John",
"age":31,
"city":"New York",
"Childs":[
{
"name":"Jim",
"age":11
},
{
"name":"Tim",
"age":9
}
]
}
Ausgabe:
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; }
}
Danach benutze ich Newtonsoft.Json , um die Klasse zu füllen:
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);
}
}
}
Sie können es so nennen:
Person jsonClass = JObjects.Get<Person>(stringJson);
string stringJson = JObjects.Get(jsonClass);
PS:
Wenn Ihr JSON-Variablenname kein gültiger C # -Name ist (Name beginnt mit $
), können Sie dies folgendermaßen beheben:
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; }
}
Dafür würde ich JSON.NET verwenden, um das Parsen des JSON-Streams auf niedriger Ebene durchzuführen und dann die Objekthierarchie aus Instanzen der ExpandoObject
Klasse aufzubauen .
Ich verwende so in meinem Code und es funktioniert gut
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
Schauen Sie sich den Artikel an, den ich über CodeProject geschrieben habe und der die Frage genau beantwortet:
Es gibt viel zu viel, um alles hier erneut zu veröffentlichen, und noch weniger Sinn, da dieser Artikel einen Anhang mit dem Schlüssel / der erforderlichen Quelldatei enthält.
Eine andere Option ist "JSON als Klassen einfügen", damit es schnell und einfach deserialisiert werden kann.
Hier ist eine bessere Erklärung n piccas ... 'JSON als Klassen einfügen ' in ASP.NET und Web Tools 2012.2 RC
Das Deserialisieren in JSON.NET kann mithilfe der JObject
Klasse, die in dieser Bibliothek enthalten ist, dynamisch sein . Meine JSON-Zeichenfolge repräsentiert diese Klassen:
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
Jetzt deserialisieren wir den String, OHNE auf die obigen Klassen zu verweisen:
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());
Oder wenn Sie tiefer gehen wollen:
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());
Ein vollständiges Beispiel finden Sie im Beitrag .
Das gewünschte Objekt DynamicJSONObject ist in der System.Web.Helpers.dll aus dem ASP.NET-Webseitenpaket enthalten, das Teil von WebMatrix ist.
Es gibt eine leichtgewichtige JSON-Bibliothek für C # SimpleJson .
Es unterstützt .NET 3.5+, Silverlight und Windows Phone 7.
Es unterstützt Dynamic für .NET 4.0
Es kann auch als NuGet-Paket installiert werden
Install-Package SimpleJson
Verwenden Sie DataSet (C #) mit JavaScript. Eine einfache Funktion zum Erstellen eines JSON-Streams mit DataSet-Eingabe. Erstellen Sie JSON-Inhalte wie (Multi-Table-Dataset):
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]
Nur Client-Seite, verwenden Sie eval. Zum Beispiel,
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}]]')
Dann benutze:
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;
}
So erhalten Sie ein ExpandoObject:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
Bitte fügen Sie die Referenz von System.Web.Extensions hinzu und fügen Sie diesen Namespace using System.Web.Script.Serialization;
oben hinzu:
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();
}
Bitte fügen Sie die Referenz von System.Web.Extensions hinzu und fügen Sie diesen Namespace using System.Web.Script.Serialization;
oben hinzu:
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();
}
Mit Cinchoo ETL - einer Open Source-Bibliothek, mit der JSON in ein dynamisches Objekt analysiert werden kann:
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);
}
}
Ausgabe:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
Haftungsausschluss: Ich bin der Autor dieser Bibliothek.
versuche es so!
JSON-Beispiel:
[{
"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 # -Code:
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()}");
}