Saya sangat suka ExpandoObject
saat menyusun objek dinamis sisi server saat runtime, tetapi saya mengalami masalah dalam meratakan hal ini selama serialisasi JSON. Pertama, saya memberi contoh objek:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
Sejauh ini baik. Di pengontrol MVC saya, saya ingin mengirimkan ini sebagai JsonResult, jadi saya melakukan ini:
return new JsonResult(expando);
Ini membuat JSON menjadi serial di bawah ini, untuk digunakan oleh browser:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
TAPI, yang benar-benar saya inginkan adalah melihat ini:
{SomeProp: SomeValueOrClass}
Saya tahu saya dapat mencapai ini jika saya menggunakan dynamic
alih-alih ExpandoObject
- JsonResult
dapat membuat serialisasi dynamic
properti dan nilai menjadi satu objek (tanpa bisnis Kunci atau Nilai), tetapi alasan saya perlu menggunakan ExpandoObject
adalah karena saya tidak tahu semua properti yang saya inginkan pada objek hingga runtime , dan sejauh yang saya tahu, saya tidak dapat secara dinamis menambahkan properti ke a dynamic
tanpa menggunakan ExpandoObject
.
Saya mungkin harus menyaring bisnis "Kunci", "Nilai" di javascript saya, tetapi saya berharap untuk mencari tahu sebelum mengirimkannya ke klien. Terima kasih atas bantuan Anda!
sumber
Jawaban:
Anda juga dapat membuat JSONConverter khusus yang hanya berfungsi untuk ExpandoObject lalu mendaftarkannya dalam sebuah instance JavaScriptSerializer. Dengan cara ini Anda dapat membuat serial array dari perluasan, kombinasi objek perluasan dan ... sampai Anda menemukan jenis objek lain yang tidak mendapatkan serialisasi dengan benar ("seperti yang Anda inginkan"), kemudian Anda membuat Konverter lain, atau menambahkan tipe lain ke yang ini. Semoga ini membantu.
Menggunakan konverter
sumber
NotImplementedException
menambahkan sesuatu sepertiserializer.Deserialize<ExpandoObject>(json);
, @theburningmonk menawarkan solusi yang berhasil untuk saya.Menggunakan JSON.NET Anda dapat memanggil SerializeObject untuk "meratakan" objek expando:
Akan menghasilkan:
Dalam konteks pengontrol ASP.NET MVC, hasil dapat dikembalikan menggunakan metode konten:
sumber
Inilah yang saya lakukan untuk mencapai perilaku yang Anda gambarkan:
Biayanya adalah Anda membuat salinan data sebelum membuat serialisasi.
sumber
ExpandoObject
memberi Anda lebih banyak fleksibilitas daripada Kamus sederhana. Meskipun contoh di atas tidak mendemonstrasikannya, Anda dapat menggunakan fitur dinamis dariExpandoObject
untuk menambahkan properti yang ingin Anda miliki di JSON Anda.Dictioanry
Objek normal akan dikonversi ke JSON tanpa masalah, jadi dengan melakukan konversi, ini adalah cara sederhana O (n) untuk menempatkan dinamika yang mudah digunakanExpandoObject
ke dalam format yang dapat JSONified. Anda benar, contoh di atas akan menjadi penggunaan redikulus dariExpandoObject
; yang sederhanaDictionary
akan jauh lebih baik.Saya menyelesaikan ini dengan menulis metode ekstensi yang mengubah ExpandoObject menjadi string JSON:
Ini menggunakan perpustakaan Newtonsoft yang sangat baik .
JsonResult kemudian terlihat seperti ini:
Dan ini dikembalikan ke browser:
Dan saya dapat menggunakannya dalam javascript dengan melakukan ini (direferensikan di sini ):
Saya harap ini membantu!
sumber
Saya dapat memecahkan masalah yang sama ini menggunakan JsonFx .
keluaran:
sumber
Saya mengambil proses perataan satu langkah lebih jauh dan memeriksa objek daftar, yang menghilangkan omong kosong nilai kunci. :)
sumber
Ini mungkin tidak berguna bagi Anda, tetapi saya memiliki persyaratan yang serupa, tetapi menggunakan SerializableDynamicObject
Saya mengubah nama kamus menjadi "Fields" dan kemudian ini bersambung dengan Json.Net untuk menghasilkan json yang terlihat seperti:
{"Fields": {"Property1": "Value1", "Property2": "Value2" dll. Di mana Properti1 dan Properti2 adalah properti yang ditambahkan secara dinamis - yaitu Kunci Kamus
Akan sempurna jika saya bisa menyingkirkan properti "Fields" ekstra yang merangkum sisanya, tetapi saya telah mengatasi batasan itu.
Jawaban dipindahkan dari pertanyaan ini atas permintaan
sumber
Ini adalah jawaban yang terlambat, tetapi saya memiliki masalah yang sama, dan pertanyaan ini membantu saya menyelesaikannya. Sebagai ringkasan, saya pikir saya harus memposting hasil saya, dengan harapan dapat mempercepat implementasi untuk orang lain.
Pertama, ExpandoJsonResult, yang dapat Anda kembalikan instance-nya dalam tindakan Anda. Atau Anda dapat mengganti metode Json di pengontrol Anda dan mengembalikannya ke sana.
Kemudian konverter (yang mendukung serialisasi dan de-serialisasi. Lihat di bawah untuk contoh cara de-serialisasi).
Anda dapat melihat di kelas ExpandoJsonResult cara menggunakannya untuk serialisasi. Untuk membatalkan serialisasi, buat serializer dan daftarkan konverter dengan cara yang sama, tetapi gunakan
Terima kasih banyak, untuk semua peserta disini yang telah membantu saya.
sumber
Menggunakan mengembalikan ExpandoObject dinamis dari WebApi di ASP.Net 4, pemformat JSON default tampaknya meratakan ExpandoObjects menjadi objek JSON sederhana.
sumber
JsonResult
penggunaanJavaScriptSerializer
yang benar-benar menghilangkan (beton)Dictionary<string, object>
seperti yang Anda inginkan.Ada kelebihan
Dictionary<string, object>
konstruktor yang membutuhkanIDictionary<string, object>
.ExpandoObject
implementsIDictionary<string, object>
(Saya pikir Anda dapat melihat ke mana saya pergi di sini ...)ExpandoObject tingkat tunggal
Satu baris kode, menggunakan semua tipe bawaan :)
ExpandoObjects bersarang
Tentu saja jika Anda bersarang
ExpandoObject
maka Anda harus secara rekursif mengonversi semuanya menjadiDictionary<string, object>
s:kode terakhir Anda menjadi
sumber
Sepertinya pembuat serial mentransmisikan Expando ke Kamus dan kemudian membuat serial (jadi bisnis Kunci / Nilai). Sudahkah Anda mencoba Deserializing as a Dictionary dan kemudian mentransmisikannya kembali ke Expando?
sumber
Saya baru saja mengalami masalah yang sama dan menemukan sesuatu yang sangat aneh. Jika aku melakukan:
Ini berfungsi, tetapi hanya jika metode saya menggunakan atribut HttpPost. Jika saya menggunakan HttpGet saya mendapatkan kesalahan. Jadi jawaban saya hanya berfungsi di HttpPost. Dalam kasus saya itu adalah Panggilan Ajax sehingga saya dapat mengubah HttpGet oleh HttpPost.
sumber