Deserialize objek json menjadi objek dinamis menggunakan Json.net

426

Apakah mungkin untuk mengembalikan objek dinamis dari deserialisasi json menggunakan json.net? Saya ingin melakukan sesuatu seperti ini:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);
irama
sumber
1
Pertimbangkan untuk menghasilkan kelas C # dari JSON json2csharp.com dan menggunakan kelas yang dihasilkan alih-alih dinamis
Michael Freidgeim
Kemungkinan duplikat Deserialize JSON ke dalam objek dinamis C #?
meJustAndrew
Bagaimana Anda menyarankan stackOverflow menutup pertanyaan sebagai "terlalu lama"? Sudah enam tahun, ada jawaban yang valid dan saran yang masuk akal untuk setiap versi .net sejak saat itu ... sangat banyak sehingga tidak lagi membantu.
andrew lorien

Jawaban:

546

Json.NET memungkinkan kita melakukan ini:

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);

Keluaran:

 1000
 string
 6

Dokumentasi di sini: LINQ ke JSON dengan Json.NET

Lihat juga JObject.Parse dan JArray.Parse

Michael Pakhantsov
sumber
36
Perhatikan bahwa untuk array sintaksnya adalah JArray.Parse.
jgillich
4
Mengapa kita perlu menggunakan kata dinamis? saya takut tidak pernah digunakan sebelumnya: D
MonsterMMORPG
3
Di VB.Net, Anda perlu melakukanDim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
ilans
2
@MonsterMMORPG Anda seharusnya :) Dynamic adalah pola anti di hampir setiap keadaan, tetapi, setiap sekarang dan nanti, Anda mungkin memiliki situasi di mana masuk akal untuk menggunakannya.
Pluc
4
Dengan Newtonsoft.Json 8.0.3 (.NET 4.5.2): Microsoft.CSharp.RuntimeBinder.RuntimeBinderException terjadi HResult = -2146233088 Pesan = 'Newtonsoft.Json.Linq.JObject' tidak mengandung definisi untuk 'number' Source = Microsoft .CSharp StackTrace: di Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError (CError pError)
user4698855
107

Pada Json.NET 4.0 Release 1, ada dukungan dinamis asli:

[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>());
}

Dan, tentu saja, cara terbaik untuk mendapatkan versi saat ini adalah melalui NuGet.

Diperbarui (11/12/2014) untuk menjawab komentar:

Ini berfungsi dengan baik. Jika Anda memeriksa jenis di debugger Anda akan melihat bahwa nilainya sebenarnya dinamis . The tipe yang mendasari adalah JObject. Jika Anda ingin mengontrol tipe (seperti menentukan ExpandoObject, maka lakukanlah.

masukkan deskripsi gambar di sini

David Peden
sumber
20
Ini sepertinya tidak pernah berhasil. Ini hanya mengembalikan JObject, bukan variabel dinamis.
Paul
12
BTW, ini berfungsi: JsonConvert.DeserializeObject <ExpandoObject> (STRING); dengan deserialisasi yang tepat, jadi kami tidak memiliki JObject dll.
Gutek
2
@ Gutek tidak yakin apa masalah Anda. Apakah Anda menjalankan kode? Saya menambahkan menegaskan untuk tes dan menambahkan properti tidak di json asli. Cuplikan layar dari debugger disertakan.
David Peden
1
@ Davidviden jika Anda memiliki JObject dan Anda akan mencoba untuk mengikatnya di Razor Anda akan mendapatkan pengecualian. Pertanyaannya adalah deserializing ke objek dinamis - JObject dinamis tetapi mengandung tipe "sendiri" seperti JValue bukan tipe primitif. Saya tidak bisa menggunakan @Model.Propnama dalam Razor jika tipe pengembaliannya adalah JValue.
Gutek
2
Ini berfungsi, tetapi setiap properti dinamis adalah a JValue. Yang membingungkan saya karena saya bekerja di debugger / jendela langsung dan tidak melihat hanya strings. David menunjukkan ini di tangkapan layar bawah. Ini JValuedapat dikonversi sehingga Anda bisa melakukannyastring m = jsonResponse.message
Luke Puplett
66

Jika Anda baru saja berhenti mendaftar untuk dinamis, Anda akan mendapatkan JObject kembali. Anda bisa mendapatkan apa yang Anda inginkan dengan menggunakan ExpandoObject.

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);
Joshua Peterson
sumber
1
Hasilnya dapat juga dikonversi ke kamus
FindOutIslamNow
1
Persis apa yang saya cari! Terima kasih!
DarkDeny
42

Saya tahu ini adalah postingan lama tetapi JsonConvert sebenarnya memiliki metode yang berbeda

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);
epitka
sumber
23
Itu akan deserializing muatan json menjadi tipe anonim, bukan tipe dinamis. Tipe anonim dan tipe dinamis adalah hal yang berbeda, dan saya tidak percaya ini menjawab pertanyaan yang diajukan.
jrista
1
Apakah perlu menggunakan dua variabel? Mengapa tidak menggunakan kembali yang pertama dalam pernyataan kedua?
RenniePet
21

Ya, Anda bisa melakukannya menggunakan JsonConvert.DeserializeObject. Untuk melakukan itu, cukup sederhana lakukan:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);
oteal
sumber
1
JsonConverttidak mengandung metode yang disebut Deserialize.
Can Poyrazoğlu
seharusnya hanya DeserializeObject, tetapi ini harus menjadi jawaban yang diterima IMO
superjugy
21

Catatan: Pada saat saya menjawab pertanyaan ini pada tahun 2010, tidak ada cara untuk deserialize tanpa semacam jenis, ini memungkinkan Anda untuk deserialize tanpa harus mendefinisikan kelas yang sebenarnya dan memungkinkan kelas anonim digunakan untuk melakukan deserialisasi.


Anda harus memiliki semacam tipe deserialize. Anda dapat melakukan sesuatu seperti:

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

Jawaban saya didasarkan pada solusi .NET 4.0 membangun JSizer serializer. Tautan ke deserialize ke jenis anonim ada di sini:

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

Phill
sumber
Saya dengan Anda phill tidak tahu mengapa orang-orang memilih ini, jika ada yang bisa tolong .. tolong jelaskan mengapa?
PEO
18
Mereka downvoting karena pertanyaannya adalah tentang deserialisasi tanpa tipe.
richard
4
Jawaban itu valid pada saat penulisan pada 2010 ketika tidak ada solusi lain. Itu bahkan jawaban yang diterima untuk periode waktu yang kecil sampai dukungan datang di JSON.NET.
Phill
1
Ini tidak menghasilkan objek yang dinamis. Ini menghasilkan JObject yang Anda referensi sebagai dinamis. Tapi itu masih JObject di dalamnya.
ghostbust555
5

Jika Anda menggunakan JSON.NET dengan versi lama yang tidak JObject.

Ini adalah cara sederhana lain untuk membuat objek dinamis dari JSON: https://github.com/chsword/jdynamic

NuGet Instal

PM> Install-Package JDynamic

Dukungan menggunakan indeks string untuk mengakses anggota seperti:

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

Kasus cobaan

Dan Anda dapat menggunakan util ini sebagai berikut:

Dapatkan nilainya secara langsung

dynamic json = new JDynamic("1");

//json.Value

2. Dapatkan anggota di objek json

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. dapat dihitung

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.

Lain

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

//json.a.a is 1.
chsword
sumber
2

Ya itu mungkin. Saya telah melakukan itu selama ini.

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

Ini agak sulit untuk tipe non asli. Misalkan di dalam Obj Anda, ada objek ClassA, dan ClassB. Mereka semua dikonversi ke JObject. Yang perlu Anda lakukan adalah:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
sk
sumber