JSON.Net Selbstreferenzierende Schleife erkannt


109

Ich habe eine MSSQL-Datenbank für meine Website in 4 Tabellen.

Wenn ich das benutze:

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

Der Code führt zu folgendem Fehler:

Newtonsoft.Json.JsonSerializationException: Selbstreferenzierende Schleife für Eigenschaft 'CyberUser' vom Typ 'DAL.CyberUser' erkannt. Pfad '[0] .EventRegistrations [0] .CyberUser.UserLogs [0]'.



Würden Sie bitte meine Antwort als richtig markieren, wenn dies der Fall ist? @ Kovu
Muhammad Omar ElShourbagy

Antworten:


210

Ich hatte gerade das gleiche Problem mit Eltern / Kind-Sammlungen und fand den Beitrag, der meinen Fall gelöst hat. Ich wollte nur die Liste der übergeordneten Sammlungselemente anzeigen und benötigte keine der untergeordneten Daten. Daher habe ich Folgendes verwendet und es hat gut funktioniert:

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

JSON.NET-Fehler Selbstreferenzierende Schleife für Typ erkannt

Es verweist auch auf die Json.NET-Codeplex-Seite unter:

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

Dokumentation: ReferenceLoopHandling-Einstellung


2
Abhängig vom Fall können Sie auch PreserveReferencesHandling = PreserveReferencesHandling.Objects;wie hier beschrieben verwenden: Lösen Sie das Problem der selbstreferenzierenden Schleife, wenn Sie newtonsoft-json verwenden
Dimitri Troncquo

In WebAPI OData v4 stellte ich fest, dass für einige Datentypen sowohl ReferenceLoopHandling.Ignore als auch PreserveReferencesHandling.Objects erforderlich waren
Chris Schaller

1
Singt Allelluiah Vielen Dank, nur eine Abstimmung um 1 ist nicht ausreichend
JP Chapleau

42

Das Update besteht darin, Schleifenreferenzen zu ignorieren und nicht zu serialisieren. Dieses Verhalten ist in angegeben JsonSerializerSettings.

SingleJsonConvert mit Überlastung:

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

Wenn Sie dies als Standardverhalten festlegen möchten , fügen Sie eine globale Einstellung mit Code Application_Start()in Global.asax.cs hinzu:

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

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


3
Die Serialisierung damit dauert für mich sehr lange
Daniel

Dies scheint nicht zu funktionieren, wenn es sich bei dem Objekt mit kreisförmigen Schleifen um NHibernate-Modell-POCOs handelt (in diesem Fall wird durch die Serialisierung eine Menge Müll abgerufen oder manchmal tritt nur eine Zeitüberschreitung auf).
Fernando Gonzalez Sanchez

"IsSecuritySafeCritical": false, "IsSecurityTransparent": false, "MethodHandle": {"Value": {"value": 140716810003120}}, "Attributes": 150, "CallingConvention": 1, "ReturnType": "System.Void" , System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e "," ReturnTypeCustomAttributes ": {" ParameterType ":" System.Void, System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e "," Name ": null," HasDefaultValue ": true," DefaultValue ": null," RawDefaultValue ": null," MetadataToken ": 134217728," Attribute ": 0," Position ": - 1, "IsIn": false, "IsLcid": false. ... etc.

36

Wenn Sie ASP.NET Core MVC verwenden, fügen Sie dies der ConfigureServices-Methode Ihrer Datei startup.cs hinzu:

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

2
Ich habe bestätigt, dass diese Lösung auch mit WebAPI EntityFramework Core 2.0
funktioniert

13

Dies kann Ihnen helfen.

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
Dies ist der beste Weg, um dies zu erreichen, wenn Sie auch asynchrone Methoden verwenden. Es kann ein echter Schmerz sein, aber es löst viele Probleme, die Sie sonst hätten (einschließlich dieses) und kann auch viel leistungsfähiger sein, da Sie nur abfragen, was Sie verwenden werden.
Josh McKearin

Öffnen Sie in Ihrer Datei xyz.edmx die Datei xyz.Context.vb, die standardmäßig ausgeblendet wird. Dies hat codePublic Sub New () Mybase.New ("name = EntityConName") End Sub code. codeFügen Sie jetzt vor End Sub Me.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False hinzu. Dadurch code wird der Fehler "Selbstreferenzierende Schleife" in Ihrer JSON-Ausgabe von Webapi beseitigt.
Venkat

Ich fand, dass das bei mir nicht funktionierte. Ich habe AsNoTracking () verwendet und es wurde behoben. Vielleicht jemand anderem helfen
scottsanpedro

@scottsanpedro Es war besser, wenn wir Ihren Code sehen konnten.
Ddagsan

6

Sie müssen Preserving Object References festlegen:

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

Dann rufen Sie Ihre Anfrage var q = (from a in db.Events where a.Active select a).ToList();gerne an

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

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


4

Fügen Sie Ihrer Modellklasse "[JsonIgnore]" hinzu

{
  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

Ich verwende Dot.Net Core 3.1 und habe nach gesucht

"Newtonsoft.Json.JsonSerializationException: Selbstreferenzierende Schleife für Eigenschaft erkannt"

Ich füge dies dieser Frage hinzu, da es eine einfache Referenz sein wird. In der Datei Startup.cs sollten Sie Folgendes verwenden:

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

2

für asp.net core 3.1.3 hat das bei mir funktioniert

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

1

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


6
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Alex Riabov

1

Manchmal haben Sie Schleifen, weil Ihre Typklasse Verweise auf andere Klassen hat und diese Klassen Verweise auf Ihre Typklasse haben. Daher müssen Sie die Parameter, die Sie benötigen, genau in der JSON-Zeichenfolge auswählen, wie diesen Code.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.