Pertanyaan Serialize Entity Framework objek ke dalam JSON


Tampaknya serialisasi objek Entity Framework ke dalam JSON tidak mungkin menggunakan data asli WCF, DataContractJsonSerializer atau serializer bawaan asli ASP.NET. Ini karena masalah penghitungan referensi yang ditolak oleh kedua serialisator. Saya juga sudah mencoba Json.NET, yang juga gagal secara khusus pada masalah Penghitungan Referensi.


Edit: Json.NET sekarang bisa serialize dan deserialize Entitas Kerangka entitas.


Objek saya adalah objek Entity Framework, yang kelebihan beban untuk melakukan fungsi bisnis tambahan (mis. Otentikasi, dll.) Dan saya tidak ingin menghias kelas-kelas ini dengan atribut khusus platform, dll. Karena saya ingin menyajikan platform-agnostic API .

Saya sudah benar-benar membuat blog tentang masing-masing langkah yang saya tempuh https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/

Apakah saya melewatkan sesuatu yang jelas?


43
2018-03-18 11:53


asal


Jawaban:


Cara saya melakukan ini adalah dengan memproyeksikan data yang ingin saya salin ke dalam sebuah tipe anonim dan serialisasi itu. Ini memastikan bahwa hanya informasi yang benar-benar saya inginkan dalam JSON yang diserialkan, dan saya tidak secara tidak sengaja membuat serialisasi sesuatu lebih jauh di bawah grafik objek. Terlihat seperti ini:

var records = from entity in context.Entities
              select new 
              {
                  Prop1 = entity.Prop1,
                  Prop2 = entity.Prop2,
                  ChildProp = entity.Child.Prop
              }
return Json(records);

Saya menemukan jenis anonim hanya tentang ideal untuk ini. JSON, jelas, tidak peduli jenis apa yang digunakan untuk memproduksinya. Dan jenis anonim memberi Anda fleksibilitas lengkap seperti apa properti dan struktur yang Anda masukkan ke JSON.


71
2018-03-18 12:30



Microsoft membuat kesalahan dalam cara mereka membuat objek EF menjadi kontrak data. Mereka termasuk kelas dasar, dan tautan belakang.

Taruhan terbaik Anda adalah membuat kelas Data Transfer Objek yang setara untuk masing-masing entitas yang ingin Anda kembalikan. Ini hanya mencakup data, bukan perilaku, dan bukan bagian khusus EF dari suatu entitas. Anda juga akan membuat metode untuk diterjemahkan ke dan dari kelas DTO Anda.

Layanan Anda kemudian akan mengembalikan Objek Transfer Data.


16
2018-03-18 12:16



Solusi saya adalah hanya menghapus referensi induk pada entitas anak saya.

Jadi dalam model saya, saya memilih hubungan dan mengubah referensi Induk menjadi Internal daripada Publik.

Mungkin bukan solusi ideal untuk semua, tetapi bekerja untuk saya.


2
2018-02-23 12:05



Berdasarkan jawaban @Craig Stuntz dan mirip dengan DTO, untuk solusi saya, saya telah membuat kelas parsial dari model (dalam file terpisah) dan metode objek kembali dengan bagaimana saya ingin hanya menggunakan properti yang akan dibutuhkan.

namespace TestApplication.Models
{
    public partial class Employee
    {
        public object ToObject()
        {
            return new
            {
                 EmployeeID = EmployeeID,
                 Name = Name,
                 Username = Username,
                 Office = Office,
                 PhoneNumber = PhoneNumber,
                 EmailAddress = EmailAddress,
                 Title = Title,
                 Department = Department,
                 Manager = Manager
            };
        }
    }
}

Dan kemudian saya menyebutnya hanya sebagai imbalan saya:

var employee = dbCtx.Employees.Where(x => x.Name == usersName).Single();
return employee.ToObject();

Saya pikir jawaban yang diterima lebih cepat dan mudah, saya hanya menggunakan metode saya untuk menyimpan semua hasil saya konsisten dan KERING.


2
2018-05-10 17:50



Satu solusi lagi jika Anda ingin memiliki konsistensi kode yang lebih baik adalah dengan menggunakan JavaScriptConverter yang akan menangani ketergantungan referensi sirkuler dan tidak akan membuat serial referensi tersebut.

Saya sudah menulis blog di sini:

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/


1
2017-09-26 14:53



FYI saya menemukan solusi alternatif

Anda dapat mengatur hubungan induk sebagai pribadi sehingga properti tidak terekspos selama terjemahan menghapus loop properti tak terbatas


1
2018-05-28 10:10



Saya berjuang dengan masalah ini selama berhari-hari,

Larutan. Di dalam jendela edmx Anda. - klik kanan dan tambahkan item pembuatan kode - Pilih tab Kode - pilih EF 4x.POCOC Entity Generator

Jika Anda tidak melihatnya, maka Anda harus menginstalnya dengan nuget, cari EF.

Generator Entitas akan menghasilkan semua jenis dan objek entitas kompleks Anda ke dalam kelas sederhana untuk berseri menjadi json.


1
2017-07-24 13:35



Saya memecahkannya dengan hanya mendapatkan jenis objek dari namespace Sistem, dan kemudian mengkonversikannya ke Kamus dan kemudian menambahkannya ke daftar. Bekerja dengan baik untuk saya :)

Kelihatannya rumit, tapi ini satu-satunya solusi umum yang berhasil untukku ... Saya menggunakan logika ini untuk pembantu yang saya buat, jadi itu untuk penggunaan khusus di mana saya harus dapat mencegat setiap jenis objek dalam objek entitas, mungkin seseorang bisa menyesuaikannya dengan penggunaannya.

List<Dictionary<string, string>> outputData = new List<Dictionary<string, string>>();

// convert all items to objects
var data = Data.ToArray().Cast<object>().ToArray();

// get info about objects; and get only those we need
// this will remove circular references and other stuff we don't need
PropertyInfo[] objInfos = data[0].GetType().GetProperties();
foreach (PropertyInfo info in objInfos) {
    switch (info.PropertyType.Namespace)
    { 
          // all types that are in "System" namespace should be OK
          case "System":
              propeties.Add(info.Name);
              break;
     }
}
Dictionary<string, string> rowsData = null;
foreach (object obj in data) {
     rowsData = new Dictionary<string, string>();
     Type objType = obj.GetType();
     foreach (string propertyName in propeties)
     {
//if You don't need to intercept every object type You could just call .ToString(), and remove other code
         PropertyInfo info = objType.GetProperty(propertyName);
         switch(info.PropertyType.FullName)
         {
               case "System.String":
                    var colData = info.GetValue(obj, null);
                    rowsData.Add(propertyName, colData != null ? colData.ToString() : String.Empty);
                    break;
//here You can add more variable types if you need so (like int and so on...)
           }
      }

      outputData .Add(rowsData); // add a new row
}

"outputData" aman untuk penyandian JSON ... Semoga seseorang akan menemukan solusi ini bermanfaat. Itu menyenangkan menulisnya :)


1
2018-01-03 13:02