Se detectó un bucle de autorreferencia JSON.Net


111

Tengo una base de datos mssql para mi sitio web dentro de 4 tablas.

Cuando uso esto:

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

El código da como resultado el siguiente error:

Newtonsoft.Json.JsonSerializationException: bucle de autorreferencia detectado para la propiedad 'CyberUser' con el tipo 'DAL.CyberUser'. Ruta '[0] .EventRegistrations [0] .CyberUser.UserLogs [0]'.



¿Podría marcar mi respuesta como correcta si lo es? @Kovu
Muhammad Omar ElShourbagy

Respuestas:


211

Acabo de tener el mismo problema con las colecciones de padres / hijos y encontré esa publicación que resolvió mi caso. Solo quería mostrar la Lista de elementos de la colección principal y no necesitaba ninguno de los datos secundarios, por lo tanto, usé lo siguiente y funcionó bien:

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

Error de JSON.NET Se detectó un bucle de autorreferencia para el tipo

también hace referencia a la página del codeplex Json.NET en:

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

Documentación: Configuración ReferenceLoopHandling


2
Dependiendo del caso, también podría usarlo PreserveReferencesHandling = PreserveReferencesHandling.Objects;como se explica aquí: resolver-problema-de-bucle-de-referencia-automática-al-usar-newtonsoft-json
Dimitri Troncquo

En WebAPI OData v4, encontré que algunos tipos de datos requerían tanto ReferenceLoopHandling.Ignore como PreserveReferencesHandling.Objects
Chris Schaller

1
Sings Allelluiah Muchas gracias, solo la votación a favor de 1 no es suficiente
JP Chapleau

42

La solución es ignorar las referencias de bucle y no serializarlas. Este comportamiento se especifica en JsonSerializerSettings.

SolteroJsonConvert con sobrecarga:

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

Si desea que este sea el comportamiento predeterminado, agregue una Configuración global con código Application_Start()en Global.asax.cs:

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

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


3
La serialización con esto me lleva mucho tiempo
Daniel

Esto no parece funcionar cuando el objeto con bucles circulares son POCO del modelo NHibernate (en ese caso, la serialización recupera una tonelada de basura o, a veces, simplemente agota el tiempo de espera).
Fernando Gonzalez Sanchez

"IsSecuritySafeCritical": falso, "IsSecurityTransparent": falso, "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 "," Nombre ": nulo," HasDefaultValue ": verdadero," DefaultValue ": nulo," RawDefaultValue ": nulo," MetadataToken ": 134217728," Atributos ": 0," Posición ": - 1, "IsIn": falso, "IsLcid": falso ,. ... etc.

37

Si usa ASP.NET Core MVC, agregue esto al método ConfigureServices de su archivo startup.cs:

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

2
Confirmé que esta solución también funciona con WebAPI EntityFramework Core 2.0
cesar-moya

13

Esto puede ayudarte.

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
Esta es la mejor manera de abordarlo si también está utilizando métodos asíncronos. Puede ser un verdadero dolor de cabeza, pero resuelve muchos problemas que tendrías de otra manera (incluido este) y también puede ser mucho más eficaz ya que solo estás preguntando qué usarás.
Josh McKearin

En su xyz.edmx, abra el archivo xyz.Context.vb que estará oculto por defecto. Esto tendrá codePublic Sub New () Mybase.New ("nombre = EntityConName") End Sub code. Ahora, antes de End Sub, agregue codeMe.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code Eso eliminará el error de 'bucle de autorreferencia' en su salida json de webapi.
Venkat

Descubrí que esto no funcionó para mí. Usé AsNoTracking () y lo arregló. Quizás ayudar a alguien más
scottsanpedro

@scottsanpedro, sería mejor si pudiéramos ver su código.
Ddagsan

6

Debe establecer Conservar referencias a objetos:

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

Luego llame a su consulta var q = (from a in db.Events where a.Active select a).ToList();como

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

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


4

Agrega "[JsonIgnore]" a tu clase de modelo

{
  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

Estoy usando Dot.Net Core 3.1 e hice una búsqueda de

"Newtonsoft.Json.JsonSerializationException: bucle de autorreferencia detectado para la propiedad"

Estoy agregando esto a esta pregunta, ya que será una referencia fácil. Debe utilizar lo siguiente en el archivo Startup.cs:

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

2

para asp.net core 3.1.3 esto funcionó para mí

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

1

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


6
Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre por qué y / o cómo este código responde a la pregunta mejora su valor a largo plazo.
Alex Riabov

1

A veces tiene bucles porque su clase de tipo tiene referencias a otras clases y esas clases tienen referencias a su clase de tipo, por lo tanto, debe seleccionar los parámetros que necesita exactamente en la cadena json, como este código.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.