Loop referensi mandiri JSON.Net terdeteksi

111

Saya memiliki database mssql untuk situs web saya dalam 4 tabel.

Saat saya menggunakan ini:

public static string GetAllEventsForJSON()
{
    using (CyberDBDataContext db = new CyberDBDataContext())
    {
        return JsonConvert.SerializeObject((from a in db.Events where a.Active select a).ToList(), new JavaScriptDateTimeConverter());
    }
}

Kode menghasilkan kesalahan berikut:

Newtonsoft.Json.JsonSerializationException: Loop referensi mandiri terdeteksi untuk properti 'CyberUser' dengan tipe 'DAL.CyberUser'. Path '[0] .EventRegistrations [0] .CyberUser.UserLogs [0]'.

PassionateDeveloper
sumber
2
kemungkinan duplikat dari JSON.NET Error Self referencing loop terdeteksi untuk tipe
Chris Moschini
Bisakah Anda menandai jawaban saya sebagai benar jika benar? @Kovu
Muhammad O Eloury
Kemungkinan duplikat loop referensi mandiri kerangka kerja Entitas terdeteksi
Michael Freidgeim

Jawaban:

212

Saya baru saja mengalami masalah yang sama dengan koleksi Parent / Child dan menemukan postingan itu yang telah menyelesaikan kasus saya. Saya Hanya ingin menampilkan Daftar item koleksi orang tua dan tidak memerlukan data anak apa pun, oleh karena itu saya menggunakan yang berikut dan berfungsi dengan baik:

JsonConvert.SerializeObject(ResultGroups, Formatting.None,
                        new JsonSerializerSettings()
                        { 
                            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                        });

Kesalahan JSON.NET Loop referensi sendiri terdeteksi untuk tipe

itu juga merujuk ke halaman codeplex Json.NET di:

http://json.codeplex.com/discussions/272371

Dokumentasi: pengaturan ReferenceLoopHandling

Muhammad Omar ElShourbagy
sumber
2
Bergantung pada kasus, Anda juga dapat menggunakan PreserveReferencesHandling = PreserveReferencesHandling.Objects;seperti yang dijelaskan di sini: selesaikan-referensi-mandiri-loop-issue-when-using-newtonsoft-json
Dimitri Troncquo
Di WebAPI OData v4, saya menemukan bahwa beberapa jenis data memerlukan ReferenceLoopHandling.Ignore dan PreserveReferencesHandling.Objects
Chris Schaller
1
Bernyanyi Allelluiah Terima kasih banyak hanya naik-voting 1 tidak cukup
JP Chapleau
42

Cara mengatasinya adalah mengabaikan referensi loop dan tidak membuat serialisasi. Perilaku ini ditentukan dalam JsonSerializerSettings.

TunggalJsonConvert dengan kelebihan beban:

JsonConvert.SerializeObject((from a in db.Events where a.Active select a).ToList(), Formatting.Indented,
    new JsonSerializerSettings() {
        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    }
);

Jika Anda ingin menjadikan ini sebagai perilaku default, tambahkan Pengaturan Global dengan kode Application_Start()di Global.asax.cs:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
     Formatting = Newtonsoft.Json.Formatting.Indented,
     ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};

Referensi: https://github.com/JamesNK/Newtonsoft.Json/issues/78

baju luar
sumber
3
Serialisasi dengan ini membutuhkan waktu yang sangat lama bagi saya
daniel
Ini tampaknya tidak berfungsi ketika objek dengan loop melingkar adalah POCO model NHibernate (dalam hal ini serialisasi mengambil banyak sampah, atau terkadang hanya waktu habis).
Fernando Gonzalez Sanchez
"IsSecuritySafeCritical": false, "IsSecurityTransparent": false, "MethodHandle": {"Value": {"value": 140716810003120}}, "Attributes": 150, "CallingConvention": 1, "ReturnType": "System.Void , System.Private.CoreLib, Versi = 4.0.0.0, Budaya = netral, PublicKeyToken = 7cec85d7bea7798e "," ReturnTypeCustomAttributes ": {" ParameterType ":" System.Void, System.Private.CoreLib, Versi = 4.0.0.0, Budaya = netral, PublicKeyToken = 7cec85d7bea7798e "," Name ": null," HasDefaultValue ": true," DefaultValue ": null," RawDefaultValue ": null," MetadataToken ": 134217728," Attributes ": 0," Position ": - 1, "IsIn": false, "IsLcid": false ,. ... dll.
37

Jika menggunakan ASP.NET Core MVC, tambahkan ini ke metode ConfigureServices dari file startup.cs Anda:

services.AddMvc()
    .AddJsonOptions(
        options => options.SerializerSettings.ReferenceLoopHandling =            
        Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );
andreisrob
sumber
2
Saya telah mengonfirmasi bahwa solusi ini juga berfungsi dengan WebAPI EntityFramework Core 2.0
cesar-moya
13

Ini dapat membantu Anda.

public MyContext() : base("name=MyContext") 
{ 
    Database.SetInitializer(new MyContextDataInitializer()); 
    this.Configuration.LazyLoadingEnabled = false; 
    this.Configuration.ProxyCreationEnabled = false; 
} 

http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

ddagsan
sumber
4
Ini adalah cara terbaik untuk mendekatinya jika Anda juga menggunakan metode asinkron. Ini bisa sangat menyebalkan, tetapi ini memecahkan banyak masalah yang seharusnya Anda alami (termasuk yang ini) dan juga bisa jauh lebih berkinerja karena Anda hanya menanyakan apa yang akan Anda gunakan.
Josh McKearin
Di xyz.edmx Anda, buka file xyz.Context.vb yang akan disembunyikan secara default. Ini akan memiliki codeSub Publik Baru () Mybase.New ("name = EntityConName") End Sub code. Sekarang sebelum End Sub tambahkan codeMe.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code Itu akan menghilangkan kesalahan 'Self referencing loop' dalam output json Anda dari webapi.
Venkat
Saya menemukan ini tidak berhasil untuk saya. Saya menggunakan AsNoTracking () dan memperbaikinya. Mungkin membantu orang lain
scottsanpedro
@scottsanpedro lebih baik jika kami dapat melihat kode Anda.
ddagsan
6

Anda harus menyetel Preserving Object References:

var jsonSerializerSettings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects
};

Kemudian panggil kueri Anda var q = (from a in db.Events where a.Active select a).ToList();seperti

string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(q, jsonSerializerSettings);

Lihat: https://www.newtonsoft.com/json/help/html/PreserveObjectReferences.htm

Cyrus
sumber
4

Tambahkan "[JsonIgnore]" ke kelas model Anda

{
  public Customer()
  {
    Orders = new Collection<Order>();
  }

public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }

[JsonIgnore]
public ICollection<Order> Orders { get; set; }
}
Samet Sunman
sumber
3

Saya menggunakan Dot.Net Core 3.1 dan melakukan pencarian

"Newtonsoft.Json.JsonSerializationException: Loop referensi mandiri terdeteksi untuk properti"

Saya menambahkan ini ke pertanyaan ini, karena ini akan menjadi referensi yang mudah. Anda harus menggunakan yang berikut ini di file Startup.cs:

 services.AddControllers()
                .AddNewtonsoftJson(options =>
                {
                    // Use the default property (Pascal) casing
                    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                });
krishnan2784
sumber
2

untuk asp.net core 3.1.3 ini berhasil untuk saya

services.AddControllers().AddNewtonsoftJson(opt=>{
            opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
Karim Tingdis
sumber
1

JsonConvert.SerializeObject(ObjectName, new JsonSerializerSettings(){ PreserveReferencesHandling = PreserveReferencesHandling.Objects, Formatting = Formatting.Indented });

pengguna3824027
sumber
6
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan tersebut meningkatkan nilai jangka panjangnya.
Alex Riabov
1

Kadang-kadang Anda memiliki loop karena kelas tipe Anda memiliki referensi ke kelas lain dan kelas itu memiliki referensi ke kelas tipe Anda, sehingga Anda harus memilih parameter yang Anda butuhkan persis dalam string json, seperti kode ini.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
Angélica Tovar
sumber