Json nesnesini Json.net kullanarak dinamik nesneye serileştirme


426

Json.net kullanarak bir json serileştirmeden dinamik bir nesne döndürmek mümkün mü? Böyle bir şey yapmak istiyorum:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);

1
JSON json2csharp.com'dan C # sınıfı oluşturmayı ve dinamik yerine oluşturulan sınıfı kullanmayı düşünün
Michael Freidgeim


StackOverflow'un bir soruyu "çok eski" olarak kapatmasını nasıl önerirsiniz? Altı yıl oldu, o zamandan beri .net'in her sürümü için geçerli cevaplar ve makul öneriler var ... o kadar ki artık gerçekten yardımcı olmuyorlar.
andrew lorien

Yanıtlar:


546

Json.NET bunu yapmamıza izin verir:

dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");

Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);

Çıktı:

 1000
 string
 6

Buradaki belgeler: Json.NET ile LINQ to JSON

Ayrıca bkz. JObject.Parse ve JArray.Parse


36
Diziler için sözdiziminin olduğunu unutmayın JArray.Parse.
jgillich

4
Neden dinamik kelime kullanmamız gerekiyor? daha önce hiç kullanmadım korkuyorum: D
MonsterMMORPG

3
Dim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
VB.Net'te

2
@MonsterMMORPG Olmanız gerekir :) Dinamik hemen hemen her koşulda bir anti-kalıptır, ancak, arada bir, onu kullanmanın makul olduğu bir durumunuz olabilir.
Pluc

4
Newtonsoft.Json 8.0.3 (.NET 4.5.2) ile: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException oluştu HResult = -2146233088 Message = 'Newtonsoft.Json.Linq.JObject', 'sayı' için bir tanım içermiyor Kaynak = Microsoft .CSharp StackTrace: Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError (CError pError)
user4698855

107

Json.NET 4.0 Sürüm 1'den itibaren yerel dinamik destek vardır:

[Test]
public void DynamicDeserialization()
{
    dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
    jsonResponse.Works = true;
    Console.WriteLine(jsonResponse.message); // Hi
    Console.WriteLine(jsonResponse.Works); // True
    Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
    Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
    Assert.That(jsonResponse, Is.TypeOf<JObject>());
}

Ve elbette, mevcut sürümü almanın en iyi yolu NuGet.

Yorumları ele almak için güncellendi (11/12/2014):

Bu mükemmel çalışıyor. Hata ayıklayıcıdaki türü incelerseniz, değerin aslında dinamik olduğunu görürsünüz . Temel tipi a, JObject. Türü kontrol etmek istiyorsanız (belirtmek gibi) ExpandoObject.

resim açıklamasını buraya girin


20
Bu asla işe yaramıyor gibi görünüyor. Dinamik bir değişken değil, yalnızca bir JObject döndürür.
Paul

12
BTW, bu çalışır: JsonConvert.DeserializeObject <ExpandoObject> (STRING); uygun bir serileştirme ile, bu yüzden JObject vb. yok
Gutek

2
@Gutek sorununun ne olduğundan emin değil. Kodu çalıştırdınız mı? Teste ekler ekledim ve orijinal json'da olmayan bir özellik ekledim. Hata ayıklayıcının ekran görüntüsü dahil.
David Peden

1
@DavidPeden JObject'iniz varsa ve Razor'da istisnalar elde edeceğinizi bağlamaya çalışacaksınız. Soru dinamik nesnenin serileştirilmesi ile ilgiliydi - JObject dinamik ancak ilkel tipler değil JValue gibi "kendi" tiplerini içeriyor. Ben kullanamaz @Model.Propdönüş tipi JValue ise Razor adı.
Gutek

2
Bu çalışır, ancak her dinamik özellik bir JValue. Hangi hata ayıklayıcı / anında penceresinde çalışıyordu ve sadece strings görmüyordu çünkü beni şaşırttı . David bunu alt ekran görüntüsünde gösterir. JValueSadece bunu yapabilirsiniz dönüştürülebilenstring m = jsonResponse.message
Luke Puplett

66

Sadece dinamiğe serileştirirseniz, bir JObject geri alırsınız. Bir ExpandoObject kullanarak istediğinizi elde edebilirsiniz.

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);

1
Sonuç ayrıca bir sözlüğe de
çevrilebilir

1
Tam olarak ne aradım! Teşekkürler!
DarkDeny

42

Bu eski yazı olduğunu biliyorum ama JsonConvert aslında farklı bir yöntemi vardır, bu yüzden olurdu

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);

23
Bu, json yükünün dinamik bir türe değil anonim bir türe serileştirilmesi olurdu. Anonim türler ve dinamik türler farklı şeylerdir ve bunun sorulan soruya hitap ettiğine inanmıyorum.
jrista

1
İki değişken kullanmak gerekli mi? Neden ikinci cümlede ilkini tekrar kullanmıyorsunuz?
RenniePet

21

Evet JsonConvert.DeserializeObject kullanarak yapabilirsiniz. Bunu yapmak için, basitçe yapın:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);

1
JsonConvertadlı bir yöntem içermiyor Deserialize.
Can Poyrazoğlu

sadece DeserializeObject olmalı, ama bu kabul edilen cevap IMO olmalıdır
superjugy

21

Not: 2010'da bu soruyu cevapladığım sırada, bir tür türü olmadan serileştirmenin bir yolu yoktu, bu, gerçek sınıfı tanımlamak zorunda kalmadan serileştirmenize izin verdi ve serileştirmeyi yapmak için anonim bir sınıfın kullanılmasına izin verdi.


Diziden serileştirmek için bir tür türünüz olması gerekir. Aşağıdakiler boyunca bir şeyler yapabilirsiniz:

var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());

Cevabım, .NET 4.0'ın JSON serileştiricisindeki derlemesi için bir çözüme dayanıyor. Anonim türlerin serileştirilmesi için bağlantı burada:

http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx


Ben seninleyim phill bilmiyorum neden insanlar bu oy, eğer herhangi biri lütfen .. lütfen nedenini açıklamak?
PEO

18
Aşağı iniyorlar, çünkü soru bir tür olmadan serileştirmeyle ilgili.
richard

4
Cevap, başka bir çözüm bulunmadığı 2010 yılında yazıldığı sırada geçerliydi. JSON.NET'te destek gelene kadar küçük bir süre bile kabul edilen cevaptı.
Phill

1
Bu dinamik bir nesne oluşturmaz. Bu, dinamik olarak başvurduğunuz bir JObject üretir. Ama hala içeride bir JObject.
ghostbust555

5

JObject olmayan eski sürümü ile JSON.NET kullanıyorsanız.

Bu, JSON'dan dinamik bir nesne oluşturmanın başka bir basit yoludur: https://github.com/chsword/jdynamic

NuGet Kurulumu

PM> Install-Package JDynamic

Üye gibi erişmek için dize dizini kullanarak destek:

dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);

Test durumu

Ve bu programı aşağıdaki gibi kullanabilirsiniz:

Değeri doğrudan alın

dynamic json = new JDynamic("1");

//json.Value

2.Json nesnesindeki üyeyi alı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 integer: 1

3.IEnumerable

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.

Diğer

dynamic json = new JDynamic("{a:{a:1} }");

//json.a.a is 1.

2

Evet mümkün. Bunu her zaman yapıyorum.

dynamic Obj = JsonConvert.DeserializeObject(<your json string>);

Doğal olmayan tip için biraz daha zor. Obj'nizin içinde bir ClassA ve ClassB nesneleri olduğunu varsayalım. Hepsi JObject'e dönüştürülür. Yapmanız gereken:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.