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

PassionateDeveloper
quelle
2
Mögliches Duplikat des JSON.NET-Fehlers Selbstreferenzierende Schleife für Typ erkannt
Chris Moschini
Würden Sie bitte meine Antwort als richtig markieren, wenn dies der Fall ist? @ Kovu
Muhammad Omar ElShourbagy
Mögliches Duplikat der selbstreferenzierenden Entity Framework-Schleife erkannt
Michael Freidgeim

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

Muhammad Omar ElShourbagy
quelle
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

Smockle
quelle
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
    );
andreisrob
quelle
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

ddagsan
quelle
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

Cyrus
quelle
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; }
}
Samet Sunman
quelle
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;
                });
krishnan2784
quelle
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;
        });
Karim Tingdis
quelle
1

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

user3824027
quelle
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
            }));
Angélica Tovar
quelle