Tentei serializar a classe POCO gerada automaticamente a partir do Entity Data Model .edmx e quando usei
JsonConvert.SerializeObject
Eu recebi o seguinte erro:
Erro O loop de auto-referência detectado para o tipo System.data.entity ocorre.
Como eu resolvo este problema?
json
serialization
json.net
NevenHuynh
fonte
fonte
async
chamada de método (aTask
) e esqueci de prefixar aawait
instrução.Respostas:
Essa foi a melhor solução https://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7
Correção 1: ignorando a referência circular globalmente
(Eu escolhi / tentei este, como muitos outros)
O serializador json.net tem uma opção para ignorar referências circulares. Coloque o seguinte código no
WebApiConfig.cs
arquivo:A correção simples fará com que o serializador ignore a referência que causará um loop. No entanto, possui limitações:
Se você deseja usar essa correção em um projeto ASP.NET que não seja da API, você pode adicionar a linha acima a
Global.asax.cs
, mas primeiro adicione:Se você quiser usar isso no projeto .Net Core , poderá alterar
Startup.cs
como:Correção 2: preservando a referência circular globalmente
Essa segunda correção é semelhante à primeira. Apenas mude o código para:
A forma dos dados será alterada após a aplicação dessa configuração.
O $ id e o $ ref mantêm todas as referências e tornam o gráfico do objeto nivelado, mas o código do cliente precisa saber a mudança de forma para consumir os dados e se aplica apenas ao serializador JSON.NET.
Correção 3: ignorar e preservar atributos de referência
Essa correção é decorar atributos na classe de modelo para controlar o comportamento de serialização no nível do modelo ou da propriedade. Para ignorar a propriedade:
JsonIgnore é para JSON.NET e IgnoreDataMember é para XmlDCSerializer. Para preservar a referência:
JsonObject(IsReference = true)]
é para JSON.NET e[DataContract(IsReference = true)]
é para XmlDCSerializer. Observe que: após aplicarDataContract
na classe, você precisa adicionarDataMember
às propriedades que deseja serializar.Os atributos podem ser aplicados no serializador json e xml e fornecem mais controles na classe de modelo.
fonte
[JsonIgnore]
acima o atributo funcionou para mim.Use JsonSerializerSettings
ReferenceLoopHandling.Error
(padrão) ocorrerá erro se um loop de referência for encontrado. É por isso que você recebe uma exceção.ReferenceLoopHandling.Serialize
é útil se os objetos estiverem aninhados, mas não indefinidamente.ReferenceLoopHandling.Ignore
não serializará um objeto se ele próprio for um objeto filho.Exemplo:
Se você precisar serializar um objeto aninhado indefinidamente, poderá usar PreserveObjectReferences para evitar uma StackOverflowException.
Exemplo:
Escolha o que faz sentido para o objeto que você está serializando.
Referência http://james.newtonking.com/json/help/
fonte
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
para que ele funcioneReferenceLoopHandling.Serialize
fará com que o serializador entre em um loop recursivo infinito e transbordará a pilha.A correção é ignorar as referências de loop e não serializá-las. Esse comportamento é especificado em
JsonSerializerSettings
.Solteiro
JsonConvert
com sobrecarga:Configuração global com código
Application_Start()
em Global.asax.cs:Referência: https://github.com/JamesNK/Newtonsoft.Json/issues/78
fonte
A maneira mais simples de fazer isso é instalar o Json.NET a partir do nuget e adicionar o
[JsonIgnore]
atributo à propriedade virtual na classe, por exemplo:Embora atualmente, eu criei um modelo com apenas as propriedades pelas quais desejo passar, para que fique mais claro, não inclua coleções indesejadas e não perco minhas alterações ao reconstruir os arquivos gerados ...
fonte
No .NET Core 1.0, você pode definir isso como uma configuração global no seu arquivo Startup.cs:
fonte
Se você estiver usando o .NET Core 2.x, atualize a seção ConfigureServices em Startup.cs
https://docs.microsoft.com/en-us/ef/core/querying/related-data#related-data-and-serialization
Se você estiver usando o .NET Core 3.x sem MVC, seria:
Esse tratamento de loop de referência é quase obrigatório se você estiver usando o Entity Framework e o padrão de design do primeiro banco de dados.
fonte
services.AddMvc()
?Para serializar-nos em NEWTONSOFTJSON quando houver um problema de loop, no meu caso, não precisei modificar global.asax ou apiconfig. Eu apenas uso JsonSerializesSettings ignorando o tratamento de loop.
fonte
Newtonsoft.Json.JsonConvert.SerializeObject(objToSerialize, new Newtonsoft.Json.JsonSerializerSettings() {ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore});
Podemos adicionar essas duas linhas no construtor de classe DbContext para desativar o loop de auto-referência, como
fonte
Você também pode aplicar um atributo à propriedade. O
[JsonProperty( ReferenceLoopHandling = ... )]
atributo é bem adequado para isso.Por exemplo:
Espero que ajude, Jaans
fonte
Para ignorar as referências de loop e não serializá-las globalmente no MVC 6, use o seguinte em startup.cs:
fonte
Use isso na
WebApiConfig.cs
aula:fonte
Para mim, tive que seguir uma rota 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 repositório base:
O objeto "context" é um parâmetro construtor que eu uso no meu repositório base porque eu uso injeção de dependência. Você pode alterar a propriedade ProxyCreationEnabled em qualquer lugar em que instanciar seu datacontext.
http://techie-tid-bits.blogspot.com/2015/09/jsonnet-serializer-and-error-self.html
fonte
Eu tive essa exceção e minha solução de trabalho é fácil e simples,
Ignore a propriedade Referenciada incluindo o atributo JsonIgnore nela:
Redefina a propriedade quando você a desserializar:
using Newtonsoft.Json;
fonte
[JsonIgnore]
Equipe:
Isso funciona com o ASP.NET Core; O desafio para o acima é como você 'define a configuração para ignorar'. Dependendo de como você configura seu aplicativo, pode ser bastante desafiador. Aqui está o que funcionou para mim.
Isso pode ser colocado na sua seção pública ConfigureServices (serviços IServiceCollection).
fonte
As pessoas já falaram sobre [JsonIgnore] ser adicionado à propriedade virtual na classe, por exemplo:
Também compartilharei outra opção, [JsonProperty (NullValueHandling = NullValueHandling.Ignore)], que omite a propriedade da serialização apenas se for nula:
fonte
Para o .NET Core 3.0, atualize a classe Startup.cs conforme mostrado abaixo.
Consulte: https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-5/
fonte
Simplesmente coloque
Configuration.ProxyCreationEnabled = false;
dentro do arquivo de contexto; Isto resolverá o problema.fonte
Meu problema resolvido com a configuração personalizada JsonSerializerSettings:
fonte
Certifique-se também de usar wait e async no seu método. Você pode obter esse erro se seu objeto não for serializado corretamente.
fonte
Eu estava enfrentando o mesmo problema e tentei usar o JsonSetting para ignorar o erro de auto-referência. Isso meio que funcionou até que eu recebi uma classe que se auto-referenciava muito profundamente e meu processo dot-net depende do valor de gravação do Json.
Meu problema
Você pode ver o problema na classe User, que está se referindo à classe CompanyUser, que é uma auto-referência.
Agora, estou chamando o método GetAll, que inclui todas as propriedades relacionais.
Nesse estágio, meu processo DotNetCore fica travado na execução do JsonResult, escrevendo valor ... e nunca chegando. No meu Startup.cs, eu já configurei o JsonOption. Por alguma razão, o EFCore está incluindo propriedades aninhadas que não estou pedindo ao Ef para fornecer.
comportamento esperado deve ser este
então
nesse estágio, eu só deveria obter esse "Company.CompanyUsers.First (). User.DisplayName" e ele não deve me fornecer Company.CompanyUsers.First (). User.CompanyUsers que causam o problema de auto-referência; Tecnicamente, ele não deve me fornecer User.CompanyUsers como CompanyUsers é uma propriedade de navegação. Mas, o EfCore fica muito animado e me oferece User.CompanyUsers .
Então, decidi escrever um método de extensão para a propriedade a ser excluída do objeto (na verdade, não está excluindo, está apenas configurando a propriedade como nula). Não apenas isso também funcionará nas propriedades da matriz. Abaixo está o código. Também vou exportar o pacote nuget para outros usuários (não tenho certeza se isso ajuda alguém). A razão é simples porque tenho preguiça de escrever .Select (n => new {n.p1, n.p2}); Eu só não quero escrever a instrução select para excluir apenas uma propriedade!
Este não é o melhor código (atualizarei em algum momento), como escrevi com pressa e, embora isso possa ajudar alguém que queira excluir (definir nulo) no objeto com matrizes também.
A classe de extensão acima permitirá que você defina a propriedade como nula para evitar o loop de auto-referência e até as matrizes.
Construtor de Expressões
Usos:
Classes de modelo
Dados fictícios
Casos:
Caso 1: excluir apenas propriedade sem nenhuma matriz
Caso 2: excluir propriedade com 1 matriz
Caso 3: excluir propriedade com 2 matrizes aninhadas
Caso 4: Consulta EF GetAll com Inclui
Você notou que o método Explode () também é um método de extensão apenas para o nosso construtor de expressões obter a propriedade da propriedade da matriz. Sempre que houver uma propriedade de matriz, use .Explode (). YourPropertyToExclude ou .Explode (). Property1.MyArrayProperty.Explode (). MyStupidProperty . O código acima me ajuda a evitar a auto-referência tão profunda quanto eu quero. Agora eu posso usar GetAll e excluir a propriedade que eu não quero!
Obrigado por ler este grande post!
fonte
Por não repetir isso funcionou para mim-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Resolvi tudo aqui - serialização de filhos do Entity Framework com .Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606
Apreciará quaisquer observações. talvez alguém possa usá-lo em algum momento.
fonte
Código c #:
fonte
Eu gostei da solução que faz isso
Application_Start()
como na resposta aquiAparentemente, não consegui acessar os objetos json no JavaScript usando a configuração dentro da minha função, como na resposta da DalSoft, pois o objeto retornado tinha "\ n \ r" em toda a (chave, val) do objeto.
De qualquer forma, tudo o que funciona é ótimo (porque abordagens diferentes funcionam em cenários diferentes, com base nos comentários e perguntas), embora uma maneira padrão de fazê-lo seja preferível com alguma boa documentação que apóie a abordagem.
fonte