Erro JSON.NET – loop de auto-referência detectado para o tipo

Tentei serializar a class POCO que foi gerada automaticamente a partir do Entity Data Model .edmx e quando usei

JsonConvert.SerializeObject 

Eu tenho o seguinte erro:

Erro O loop de auto-referência detectado para o tipo System.data.entity ocorre.

Como eu resolvo este problema?

Essa foi a melhor solução http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Correção 1: Ignorando referência circular globalmente

(Eu escolhi / tentei este, assim como muitos outros)

O serializador json.net tem uma opção para ignorar referências circulares. Coloque o seguinte código no arquivo WebApiConfig.cs :

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

A correção simples fará com que o serializador ignore a referência que causará um loop. No entanto, tem limitações:

Os dados perdem as informações de referência de loop A correção só se aplica a JSON.net O nível de referências não pode ser controlado se houver uma cadeia de referência profunda

Se você quiser usar essa correção em um projeto ASP.NET não-api, você pode adicionar a linha acima para Global.asax.cs , mas primeiro adicione:

 var config = GlobalConfiguration.Configuration; 

Se você quiser usar isso no projeto .Net Core , você pode alterar o Startup.cs como:

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

Fix 2: Preservando a referência circular globalmente

Essa segunda correção é semelhante à primeira. Apenas mude o código para:

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

A forma dos dados será alterada após a aplicação dessa configuração.

 [ { "$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" } ] 

O $ id e o $ ref mantêm todas as referências e tornam o nível do gráfico de object estável, mas o código do cliente precisa conhecer a mudança de forma para consumir os dados e também se aplica apenas ao serializador JSON.NET.

Correção 3: Ignore e preserve os atributos de referência

Essa correção é decorar atributos na class de modelo para controlar o comportamento de serialização no nível do modelo ou da propriedade. Para ignorar a propriedade:

 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 é para JSON.NET e IgnoreDataMember é para XmlDCSerializer. Para preservar a referência:

 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)] é para JSON.NET e [DataContract(IsReference = true)] é para XmlDCSerializer. Observe que: depois de aplicar DataContract na class, você precisa adicionar DataMember às propriedades que deseja serializar.

Os atributos podem ser aplicados no serializador json e xml e fornecem mais controles na class de modelo.

Use JsonSerializerSettings

  • ReferenceLoopHandling.Error (padrão) terá erro se um loop de referência for encontrado. É por isso que você recebe uma exceção.
  • ReferenceLoopHandling.Serialize é útil se os objects estiverem nesteds, mas não indefinidamente.
  • ReferenceLoopHandling.Ignore não serializará um object se for um object filho de si mesmo.

Exemplo:

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

Se você precisar serializar um object nested indefinidamente, use PreserveObjectReferences para evitar uma StackOverflowException.

Exemplo:

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

Escolha o que faz sentido para o object que você está serializando.

Referência http://james.newtonking.com/json/help/

A correção é ignorar as referências de loop e não serializá-las. Esse comportamento é especificado em JsonSerializerSettings .

JsonConvert único com uma sobrecarga:

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

Configuração global com código em Application_Start() em Global.asax.cs:

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

Referência: https://github.com/JamesNK/Newtonsoft.Json/issues/78

A maneira mais simples de fazer isso é instalar o Json.NET a partir do nuget e adicionar o atributo [JsonIgnore] à propriedade virtual da class, por exemplo:

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

Apesar de hoje em dia, eu crio um modelo com apenas as propriedades que eu quero passar, então ele é mais claro, não inclui collections indesejadas, e eu não perco minhas alterações quando eu reconstruo os arquivos gerados …

No .NET Core 1.0, você pode definir isso como uma configuração global no arquivo 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)); }); } 

Podemos adicionar essas duas linhas no construtor de class DbContext para desativar o loop de auto-referência, como

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

Você também pode aplicar um atributo à propriedade. O [JsonProperty( ReferenceLoopHandling = ... )] é bem adequado para isso.

Por exemplo:

 ///  /// 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... } 

Espero que ajude, Jaans

Para ignorar referências de loop e não serializá-las globalmente no MVC 6, use o seguinte em 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); }); } 

Use isso na class WebApiConfig.cs :

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

Para mim eu tive que seguir um caminho diferente. Em vez de tentar consertar o serializador JSON.Net, tive que ir atrás do Lazy Loading no meu datacontext.

Acabei de adicionar isso ao meu repository base:

 context.Configuration.ProxyCreationEnabled = false; 

O object “context” é um parâmetro construtor que eu uso no meu repository base porque eu uso injeção de dependência. Você pode alterar a propriedade ProxyCreationEnabled em qualquer lugar para instanciar seu datacontext.

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

Para serializar usin NEWTONSOFTJSON quando você tem problema de loop, no meu caso eu não precisava modificar global.asax ou apiconfig. Eu apenas uso o JsonSerializesSettings, ignorando o manuseio do 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); 

Eu tive essa exceção e minha solução de trabalho é fácil e simples,

Ignore a propriedade Referenced adicionando o atributo JsonIgnore a ele:

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

Redefinir a propriedade quando você desserializar:

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

usando Newtonsoft.Json;

Se você estiver usando o .NET Core 2.0, atualize sua seção ConfigureServices em Startup.cs

http://www.google.com/adwords

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

As pessoas já falaram sobre [JsonIgnore] para ser adicionado à propriedade virtual na class, por exemplo:

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

Também compartilharei uma outra opção, [JsonProperty (NullValueHandling = NullValueHandling.Ignore)], que omite a propriedade da serialização somente se for nula.

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

Simplesmente coloque Configuration.ProxyCreationEnabled = false; dentro do arquivo de contexto; Isto resolverá o problema.

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

Para não looping isso funcionou para mim-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

Eu resolvi tudo aqui – serialização de crianças do Entity Framework com .Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606

Apreciará quaisquer observações. talvez alguém possa usá-lo algum dia.

Eu gostei da solução que faz isso de Application_Start() como na resposta aqui

Aparentemente eu não consegui acessar os objects json em JavaScript usando a configuração dentro da minha function como na resposta do DalSoft, pois o object retornado tinha “\ n \ r” em todo o (key, val) do object.

De qualquer forma, o que funciona é ótimo (porque abordagens diferentes funcionam em cenários diferentes com base nos comentários e perguntas feitas), embora uma maneira padrão de fazê-lo seja preferível com uma boa documentação que suporte a abordagem.