Errore JSON.NET Rilevato loop di riferimento automatico per tipo

Ho provato a serializzare la class POCO che è stata generata automaticamente da Entity Data Model .edmx e quando l’ho usata

JsonConvert.SerializeObject 

Ho ricevuto il seguente errore:

Errore Rilevato loop autoreferenziale rilevato per tipo System.data.entity.

Come risolvo questo problema?

Questa era la soluzione migliore http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Fix 1: ignorare il riferimento circolare globalmente

(Ho scelto / provato questo, come molti altri)

Il serializzatore json.net ha un’opzione per ignorare i riferimenti circolari. Inserisci il seguente codice nel file WebApiConfig.cs :

  config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

La semplice correzione farà sì che il serializzatore ignori il riferimento che causerà un loop. Tuttavia, ha limitazioni:

I dati perdono le informazioni di riferimento del loop La correzione si applica solo a JSON.net Il livello dei riferimenti non può essere controllato se esiste una catena di riferimento profonda

Se si desidera utilizzare questa correzione in un progetto ASP.NET non API, è ansible aggiungere la riga sopra a Global.asax.cs , ma prima aggiungere:

 var config = GlobalConfiguration.Configuration; 

Se si desidera utilizzare questo nel progetto .Net Core , è ansible modificare Startup.cs come:

  var mvc = services.AddMvc(options => { ... }) .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); 

Correzione 2: conservazione del riferimento circolare globalmente

Questa seconda correzione è simile alla prima. Basta cambiare il codice per:

 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize; config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 

La forma dei dati verrà modificata dopo aver applicato questa impostazione.

 [ { "$id":"1", "Category":{ "$id":"2", "Products":[ { "$id":"3", "Category":{ "$ref":"2" }, "Id":2, "Name":"Yogurt" }, { "$ref":"1" } ], "Id":1, "Name":"Diary" }, "Id":1, "Name":"Whole Milk" }, { "$ref":"3" } ] 

$ Id e $ ref conservano tutti i riferimenti e rendono il livello dell’object grafico piatto, ma il codice client deve conoscere la modifica della forma per consumare i dati e si applica solo al serializzatore JSON.NET.

Fix 3: Ignora e conserva gli attributi di riferimento

Questa correzione è decorare gli attributi sulla class del modello per controllare il comportamento della serializzazione a livello di modello o di proprietà. Per ignorare la proprietà:

 1: public class Category 2: { 3: public int Id { get; set; } 4: public string Name { get; set; } 5: 6: [JsonIgnore] 7: [IgnoreDataMember] 8: public virtual ICollection Products { get; set; } 9: } 

JsonIgnore è per JSON.NET e IgnoreDataMember è per XmlDCSerializer. Per conservare il riferimento:

 1: // Fix 3 2: [JsonObject(IsReference = true)] 3: public class Category 4: { 5: public int Id { get; set; } 6: public string Name { get; set; } 7: 8: // Fix 3 9: //[JsonIgnore] 10: //[IgnoreDataMember] 11: public virtual ICollection Products { get; set; } 12: } 13: 14: [DataContract(IsReference = true)] 15: public class Product 16: { 17: [Key] 18: public int Id { get; set; } 19: 20: [DataMember] 21: public string Name { get; set; } 22: 23: [DataMember] 24: public virtual Category Category { get; set; } 25: } 

JsonObject(IsReference = true)] è per JSON.NET e [DataContract(IsReference = true)] è per XmlDCSerializer. Si noti che: dopo aver applicato DataContract sulla class, è necessario aggiungere DataMember alle proprietà che si desidera serializzare.

Gli attributi possono essere applicati su serializer json e xml e forniscono più controlli sulla class del modello.

Usa JsonSerializerSettings

  • ReferenceLoopHandling.Error (default) errore se si incontra un loop di riferimento. Questo è il motivo per cui ottieni un’eccezione.
  • ReferenceLoopHandling.Serialize è utile se gli oggetti sono nidificati ma non indefinitamente.
  • ReferenceLoopHandling.Ignore non serializza un object se è un object figlio di se stesso.

Esempio:

 JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize }); 

Se si deve serializzare un object che è annidato indefinitamente, è ansible utilizzare PreserveObjectReferences per evitare una StackOverflowException.

Esempio:

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

Scegli cosa ha senso per l’object che stai serializzando.

Riferimento http://james.newtonking.com/json/help/

La correzione è ignorare i riferimenti del ciclo e non serializzarli. Questo comportamento è specificato in JsonSerializerSettings .

Singolo JsonConvert con un sovraccarico:

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

Impostazioni globali con codice in Application_Start() in Global.asax.cs:

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

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

Il modo più semplice per farlo è installare Json.NET da nuget e aggiungere l’attributo [JsonIgnore] alla proprietà virtuale nella class, ad esempio:

  public string Name { get; set; } public string Description { get; set; } public Nullable Project_ID { get; set; } [JsonIgnore] public virtual Project Project { get; set; } 

Anche se in questi giorni, creo un modello con solo le proprietà che voglio passare, quindi è più leggero, non include le raccolte indesiderate e non perdo le mie modifiche quando ricostruisco i file generati …

In .NET Core 1.0, è ansible impostarlo come impostazione globale nel file Startup.cs:

 using System.Buffers; using Microsoft.AspNetCore.Mvc.Formatters; using Newtonsoft.Json; // beginning of Startup class public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.OutputFormatters.Clear(); options.OutputFormatters.Add(new JsonOutputFormatter(new JsonSerializerSettings(){ ReferenceLoopHandling = ReferenceLoopHandling.Ignore, }, ArrayPool.Shared)); }); } 

Possiamo aggiungere queste due linee nel costruttore della class DbContext per disabilitare il loop di Self referencing, come

 public TestContext() : base("name=TestContext") { this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; } 

Puoi anche applicare un attributo alla proprietà. L’ [JsonProperty( ReferenceLoopHandling = ... )] è adatto a questo.

Per esempio:

 ///  /// Represents the exception information of an event ///  public class ExceptionInfo { // ...code omitted for brevity... ///  /// An inner (nested) error. ///  [JsonProperty( ReferenceLoopHandling = ReferenceLoopHandling.Ignore, IsReference = true )] public ExceptionInfo Inner { get; set; } // ...code omitted for brevity... } 

Spero che aiuti, Jaans

Per ignorare i riferimenti del ciclo e non serializzarli globalmente in MVC 6, utilizzare quanto segue in startup.cs:

  public void ConfigureServices(IServiceCollection services) { services.AddMvc().Configure(options => { options.OutputFormatters.RemoveTypesOf(); var jsonOutputFormatter = new JsonOutputFormatter(); jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; options.OutputFormatters.Insert(0, jsonOutputFormatter); }); } 

Usalo nella class WebApiConfig.cs :

 var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter); 

Per me ho dovuto seguire una strada diversa. Invece di provare a sistemare il serializzatore JSON.Net, sono dovuto andare dopo il Lazy Loading sul mio datacontext.

Ho appena aggiunto questo al mio repository di base:

 context.Configuration.ProxyCreationEnabled = false; 

L’object “context” è un parametro costruttore che utilizzo nel mio repository di base perché utilizzo dependency injection. È ansible modificare la proprietà ProxyCreationEnabled ovunque si instanzia invece il proprio datacontext.

http://techie-tid-bits.blogspot.com/2015/09/jsonnet-serializer-and-error-self.html

Per serializzare in NEWTONSOFTJSON quando si ha un problema di loop, nel mio caso non avevo bisogno di modificare global.asax o apiconfig. Io uso solo JsonSerializesSettings ignorando la gestione del Looping.

 JsonSerializerSettings jss = new JsonSerializerSettings(); jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; var lst = db.shCards.Where(m => m.CardID == id).ToList(); string json = JsonConvert.SerializeObject(lst, jss); 

Ho avuto questa eccezione e la mia soluzione di lavoro è semplice e facile,

Ignora la proprietà di riferimento aggiungendo l’attributo JsonIgnore ad esso:

 [JsonIgnore] public MyClass currentClass { get; set; } 

Ripristina la proprietà quando la deserializzi:

 Source = JsonConvert.DeserializeObject(JsonTxt); foreach (var item in Source) { Source.MyClass = item; } 

utilizzando Newtonsoft.Json;

Se utilizzi .NET Core 2.0, aggiorna la sezione ConfiguraServices in Startup.cs

https://docs.microsoft.com/en-us/ef/core/querying/related-data#related-data-and-serialization

 public void ConfigureServices(IServiceCollection services) { ... services.AddMvc() .AddJsonOptions( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore ); ... } 

Le persone hanno già parlato di [JsonIgnore] da aggiungere alla proprietà virtuale nella class, ad esempio:

 [JsonIgnore] public virtual Project Project { get; set; } 

Condividerò anche un’altra opzione, [JsonProperty (NullValueHandling = NullValueHandling.Ignore)] che omette la proprietà dalla serializzazione solo se è nullo.

 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public virtual Project Project { get; set; } 

Basta posizionare Configuration.ProxyCreationEnabled = false; all’interno del file di contesto; questo risolverà il problema.

 public demEntities() : base("name=demEntities") { Configuration.ProxyCreationEnabled = false; } 

Per non fare il loop questo ha funzionato per me-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

Ho risolto tutto qui – La serializzazione dei bambini di Entity Framework con .Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606

Apprezzerà qualsiasi osservazione forse qualcuno può usarlo qualche volta.

Mi è piaciuta la soluzione che fa da Application_Start() come nella risposta qui

Apparentemente non ho potuto accedere agli oggetti JSON in JavaScript usando la configurazione all’interno della mia funzione come nella risposta di DalSoft poiché l’object restituito aveva “\ n \ r” su tutta la (chiave, val) dell’object.

Comunque, qualunque cosa funzioni è grande (perché diversi approcci funzionano in diversi scenari basati sui commenti e le domande poste) sebbene un modo standard di farlo sarebbe preferibile con una buona documentazione che supporti l’approccio.