JSON.Net Kendinden referans alma döngüsü algılandı


111

Web sitem için 4 tablo içinde bir mssql veritabanım var.

Bunu kullandığımda:

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

Kod, aşağıdaki hatayla sonuçlanır:

Newtonsoft.Json.JsonSerializationException: 'CyberUser' özelliği için 'DAL.CyberUser' türünde kendi kendine başvuran döngü algılandı. Yol '[0] .EventRegistrations [0] .CyberUser.UserLogs [0]'.



Cevabımı doğru ise lütfen işaretler misiniz? @Kovu
Muhammad Omar ElShourbagy

Yanıtlar:


212

Ebeveyn / Çocuk koleksiyonlarında da aynı sorunu yaşadım ve davamı çözen gönderiyi buldum. Yalnızca üst koleksiyon öğelerinin Listesini göstermek istedim ve alt verilere ihtiyaç duymadım, bu nedenle aşağıdakileri kullandım ve iyi çalıştı:

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

JSON.NET Hatası Tür için kendi kendine referans döngüsü algılandı

ayrıca şu adresteki Json.NET codeplex sayfasına da başvurur:

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

Belgeler: ReferenceLoopHandling ayarı


2
Ayrıca kullanabilirsiniz durumunda bağlı PreserveReferencesHandling = PreserveReferencesHandling.Objects;olarak burada açıklanmıştır: çözmek-kendinden referanslı döngü-konu-zaman-kullanma-newtonsoft-json
Dimitri Troncquo

WebAPI OData v4'te, bazı veri türlerinin hem ReferenceLoopHandling.Ignore hem de PreserveReferencesHandling.Objects
Chris Schaller

1
Söylüyor Allelluiah Teşekkürler, sadece 1 kadar oy vermek yeterli değil
JP Chapleau

42

Düzeltme, döngü referanslarını yok saymak ve bunları serileştirmek değil. Bu davranış içinde belirtilmiştir JsonSerializerSettings.

TekJsonConvert bir aşırı ile:

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

Bunu varsayılan davranış yapmak istiyorsanız , Global.asax.cs içindeki kodu içeren bir Global Ayar ekleyin Application_Start():

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

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


3
Bununla serileştirme benim için çok uzun zaman alıyor
daniel

Bu, dairesel döngülere sahip nesne NHibernate model POCO'lar olduğunda işe yaramıyor gibi görünüyor (bu durumda serileştirme bir ton çöpü geri getiriyor veya bazen zaman aşımına uğruyor).
Fernando Gonzalez Sanchez

"IsSecuritySafeCritical": false, "IsSecurityTransparent": false, "MethodHandle": {"Değer": {"değer": 140716810003120}}, "Nitelikler": 150, "CallingConvention": 1, "ReturnType": "System.Void , System.Private.CoreLib, Sürüm = 4.0.0.0, Culture = nötr, PublicKeyToken = 7cec85d7bea7798e "," ReturnTypeCustomAttributes ": {" ParameterType ":" System.Void, System.Private.CoreLib, Sürüm = 4.0.0.0, Culture = nötr, PublicKeyToken = 7cec85d7bea7798e "," Ad ": null," HasDefaultValue ": true," DefaultValue ": null," RawDefaultValue ": null," MetadataToken ": 134217728," Nitelikler ": 0," Konum ": - 1, "IsIn": false, "IsLcid": false ,. ... vb.

37

ASP.NET Core MVC kullanıyorsanız, bunu startup.cs dosyanızın ConfigureServices yöntemine ekleyin:

services.AddMvc()
    .AddJsonOptions(
        options => options.SerializerSettings.ReferenceLoopHandling =            
        Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );

2
Bu çözümün WebAPI EntityFramework Core 2.0 ile de çalıştığını doğruladım
cesar-moya

13

Bu size yardımcı olabilir.

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
Eşzamansız yöntemler de kullanıyorsanız, buna yaklaşmanın en iyi yolu budur. Gerçek bir acı olabilir, ancak aksi takdirde sahip olabileceğiniz birçok sorunu çözer (bu da dahil) ve yalnızca ne kullanacağınızı sorguladığınız için çok daha performanslı olabilir.
Josh McKearin

Xyz.edmx'inizde, varsayılan olarak gizlenecek olan xyz.Context.vb dosyasını açın. Bu, codePublic Sub New () Mybase.New ("name = EntityConName") End Sub code. Şimdi End codeSub'dan önce Me.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code ekleyin.
Venkat

Bunun benim için işe yaramadığını buldum. AsNoTracking () kullandım ve düzeltti. Belki başka birine yardım edebilirim
scottsanpedro

@scottsanpedro Kodunuzu görebilseydik daha iyi olurdu.
ddagsan

6

Korunan Nesne Referanslarını ayarlamalısınız:

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

Sonra sorgu çağırmak var q = (from a in db.Events where a.Active select a).ToList();gibi

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

Bakınız: https://www.newtonsoft.com/json/help/html/PreserveObjectReferences.htm


4

Model sınıfınıza "[JsonIgnore]" ekleyin

{
  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

Dot.Net Core 3.1 kullanıyorum ve bir arama yaptım

"Newtonsoft.Json.JsonSerializationException: Özellik için kendi kendine başvuru döngüsü algılandı"

Bunu da kolay bir referans olacağı için bu soruya ekliyorum. Startup.cs dosyasında aşağıdakileri kullanmalısınız:

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

2

asp.net core 3.1.3 için bu benim için çalıştı

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

1

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


6
Bu kod soruyu yanıtlayabilirken, bu kodun soruyu neden ve / veya nasıl yanıtladığına ilişkin ek bağlam sağlamak, uzun vadeli değerini artırır.
Alex Riabov

1

Bazen, tür sınıfınızın diğer sınıflara başvuruları olduğu ve sınıfların tür sınıfınıza başvuruları olduğu için döngüleriniz olur, bu nedenle tam olarak ihtiyacınız olan parametreleri json dizesinde bu kod gibi seçmeniz gerekir.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.