JSON içeriğini bir C # 4 dinamik türüne serileştirmenin bir yolu var mı? Kullanmak için bir grup sınıf oluşturmayı atlamak güzel olurdu DataContractJsonSerializer
.
JSON içeriğini bir C # 4 dinamik türüne serileştirmenin bir yolu var mı? Kullanmak için bir grup sınıf oluşturmayı atlamak güzel olurdu DataContractJsonSerializer
.
Yanıtlar:
Derlemeye bağımlı olmaktan mutluluk System.Web.Helpers
duyarsanız, Json
sınıfı kullanabilirsiniz :
dynamic data = Json.Decode(json);
MVC çerçevesine , .NET 4 çerçevesine ek bir indirme olarak eklenmiştir . Vlad'ın yararlı olduğunu düşünüyorsanız bir oy verin! Ancak istemci ortamının bu DLL'yi içerdiğini varsayamıyorsanız, okumaya devam edin.
Burada alternatif bir serileştirme yaklaşımı önerilmektedir . Bir hatayı düzeltmek ve kodlama stilime uyacak şekilde kodu biraz değiştirdim. Tek ihtiyacınız olan bu kod ve System.Web.Extensions
projenizden bir referans :
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
}
Bu şekilde kullanabilirsiniz:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
Yani, bir JSON dizesi verildiğinde:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
Aşağıdaki kod çalışma zamanında çalışır:
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 # bir anahtar kelime olan) ile aynı sorun vardı . Buna ek olarak TryGetMember
, geçersiz kılınabilir TryGetIndex
, bu da JS'dekiyle aynı davranışı verir. Daha sonra alan adlarını obj["params"]
veya obj["background-color"]
alan adlarını yapabilirsiniz.
Json.NET kullanarak oldukça basit :
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Ayrıca 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;
Belgeler: JSON'u dinamik olarak sorgulama
stuff
:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
yöntemin içinde olmak üzere daralttım . Yöntemi senkronize yaparsam beklendiği gibi çalışır. Ancak, yöntem yapmak async
ve ben olamaz bir olsun dynamic
, ben sadece bir olsun object
. Açık döküm hiçbir şey yapmaz, yine de bana bir verir object
. Bunu yaşayan başka biri var mı?
Bunu System.Web.Helpers.Json kullanarak yapabilirsiniz - Kod Çözme yöntemi istediğiniz gibi gezebileceğiniz dinamik bir nesne döndürür.
System.Web.Helpers derlemesinde (.NET 4.0) bulunur.
var dynamicObject = Json.Decode(jsonString);
.NET 4.0'da bunu yapmak için yerleşik bir kitaplık vardır:
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
Bu en basit yol.
Dictionary<string,object>
. Bir şeyi kaçırmadıkça, örneğin dinamik bir nesne döndürmez.
we already know how to get the dictionary and casting it to a dynamic
,. Bir sözlük olmak zorunda değildir. Json'un sözlük dışında da listeleri var. Ayrıca listeler ve sözlükler de iç içe olabilir. Kodum tüm bu durumları işleyebilir. AMA yönteminiz YAPILAMAZ.
IDynamicMetaObjectProvider
(veya örn. kullanmak ExpandoObject
) mümkündür . Bu dynamic
, kodun kullanılmasına izin d.code
verilmesi ile birlikte kullanılır. Bir sözlüğü bir dinamiğe dökmek anlamsızdır.
Herhangi bir üçüncü taraf DLL dosyası olmadan nesneye basit "dize JSON verileri":
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
Not: Özel nesnenizi de kullanabilirsiniz.
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
misiniz? Çalışma zamanında yapıldığını biliyorum, ancak üzerinden erişme nasıl myObject["myprop"]
geçerli?
JsonFx , JSON içeriğinin dinamik nesnelerde serisini kaldırabilir.
Dinamik türlere / türlerinden seri hale getirme (.NET 4.0 için varsayılan):
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]}
Expando Nesneleri kullanan yeni bir DynamicJsonConverter sürümü yaptım. Genişletme nesneleri kullandım, çünkü Json.NET kullanarak dinamiği tekrar JSON'a Serialize etmek istedim.
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 kullanarak başka bir yol :
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
Bunu Newtonsoft.Json yardımıyla elde edebilirsiniz. Nuget'ten Newtonsoft.Json uygulamasını kurun ve:
using Newtonsoft.Json;
dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
En basit yol:
Sadece bu DLL dosyasını ekleyin .
Kodu şu şekilde kullanın:
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'ı, oluşturduğu sözlüğü genişleterek nesnelere genişletmek ve bunları dinamik olarak kullanmak için genişletebilirsiniz:
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;
}
}
O zaman sadece uzantıyı tanımladığınız ad alanı için bir kullanım ifadesine sahip olmanız gerekir (bunları System.Web.Script.Serialization'da tanımlamayı düşünün ... başka bir hile bir ad alanı kullanmamaktır, o zaman ifadesi) ve bunları şu şekilde tüketebilirsiniz:
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
Kullanabilirsiniz using Newtonsoft.Json
var jRoot =
JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
benim cevabım çekirdek olayı çağırmaktan geliyor
Ben JSON nesnesini temsil eden bir sınıf almak için http://json2csharp.com/ kullanın.
Giriş:
{
"name":"John",
"age":31,
"city":"New York",
"Childs":[
{
"name":"Jim",
"age":11
},
{
"name":"Tim",
"age":9
}
]
}
Çıktı:
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; }
}
Bundan sonra sınıfı doldurmak için Newtonsoft.Json kullanın:
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);
}
}
}
Buna şöyle diyebilirsiniz:
Person jsonClass = JObjects.Get<Person>(stringJson);
string stringJson = JObjects.Get(jsonClass);
Not:
JSON değişken adınız geçerli bir C # adı değilse (ad ile başlar $
) bunu şu şekilde düzeltebilirsiniz:
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; }
}
Bunun için JSON akışının alt düzey ayrıştırma yapmak ve daha sonra ExpandoObject
sınıf örnekleri dışında nesne hiyerarşisi oluşturmak için JSON.NET kullanabilirsiniz .
Kodumda böyle kullanıyorum ve iyi çalışıyor
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
CodeProject üzerine yazdığım ve soruyu tam olarak cevaplayan makaleye bakın:
Burada yeniden yayınlamak için çok fazla yol var ve bu makalenin anahtar / gerekli kaynak dosyasıyla bir eki olduğundan daha az nokta var.
Başka bir seçenek de "JSON'u sınıflar olarak yapıştırmak "tır, böylece hızlı ve kolay bir şekilde serileştirilebilir.
İşte daha iyi bir açıklama n piccas ... ASP.NET ve Web Araçları 2012.2 RC'de 'JSON Sınıf Olarak Yapıştır'
JSON.NET içindeki serileştirme, JObject
bu kitaplıkta bulunan sınıfı kullanarak dinamik olabilir . JSON dizem şu sınıfları temsil eder:
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
Şimdi yukarıdaki sınıflara başvurmadan dizeyi serileştiriyoruz:
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());
Veya daha derine inmek istiyorsanız:
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());
Tam bir örnek için gönderiye bakın .
DynamicJSONObject istediğiniz nesne, WebMatrix'in bir parçası olan ASP.NET Web Sayfaları paketinden System.Web.Helpers.dll dosyasına eklenir.
SimpleJson adlı C # için hafif bir JSON kütüphanesi var .
.NET 3.5+, Silverlight ve Windows Phone 7'yi destekler.
.NET 4.0 için dinamik desteği
NuGet paketi olarak da kurulabilir
Install-Package SimpleJson
JavaScript ile DataSet (C #) kullanın. DataSet girişi ile bir JSON akışı oluşturmak için basit bir işlev. Şunun gibi JSON içeriği oluşturun (çoklu tablo veri kümesi):
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]
Sadece müşteri tarafında, eval kullanın. Örneğin,
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}]]')
Sonra kullan:
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 almak için:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
Lütfen System.Web.Extensions referansını ekleyin ve bu ad alanını using System.Web.Script.Serialization;
en üste ekleyin :
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();
}
Lütfen System.Web.Extensions referansını ekleyin ve bu ad alanını using System.Web.Script.Serialization;
en üste ekleyin :
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'u dinamik bir nesneye ayrıştırmak için kullanılabilen açık kaynaklı bir kütüphane olan Cinchoo ETL ile :
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);
}
}
Çıktı:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
Feragatname: Bu kütüphanenin yazarıyım.
bu şekilde dene!
JSON örneği:
[{
"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 # kodu:
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()}");
}