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]'.



Bisakah Anda menandai jawaban saya sebagai benar jika benar? @Kovu
Muhammad O Eloury

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


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


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

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


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


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

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

2

untuk asp.net core 3.1.3 ini berhasil untuk saya

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

1

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


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
            }));
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.