检测到JSON.Net自引用循环


110

我的网站内有4个表的mssql数据库。

当我使用这个:

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

该代码导致以下错误:

Newtonsoft.Json.JsonSerializationException:为类型为“ DAL.Cyber​​User”的属性“ Cyber​​User”检测到自引用循环。路径'[0] .EventRegistrations [0] .Cyber​​User.UserLogs [0]'。



如果我的答案正确,请您将其标记为正确吗?@Kovu
Muhammad Omar ElShourbagy

Answers:


211

我只是对Parent / Child集合有同样的问题,发现该帖子解决了我的问题。我只想显示父集合项的列表,不需要任何子数据,因此我使用了以下内容,并且工作正常:

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

JSON.NET错误检测到类型的自引用循环

它还在以下位置引用了Json.NET Codeplex页面:

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

文档:ReferenceLoopHandling设置


2
根据情况的不同,您还可以PreserveReferencesHandling = PreserveReferencesHandling.Objects;按以下说明使用 :解决自我引用循环问题,何时使用newtonsoft-json
Dimitri Troncquo '18

在WebAPI OData v4中,我发现某些类型的数据都需要ReferenceLoopHandling.Ignore和PreserveReferencesHandling.Objects
Chris Schaller

1
Sings Allelluiah非常感谢,仅靠1投票是不够的
JP

42

解决方法是忽略循环引用,而不是序列化它们。在中指定了此行为JsonSerializerSettings

JsonConvert重载:

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

如果要将其设为默认行为,请在Global.asax.cs中添加代码中的“ 全局设置”Application_Start()

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

参考:https : //github.com/JamesNK/Newtonsoft.Json/issues/78


3
序列化对我来说需要很长时间
丹尼尔(Daniel)

当带有循环循环的对象是NHibernate模型POCO时,这似乎不起作用(在这种情况下,序列化会检索大量垃圾,或者有时只是超时)。
费尔南多·冈萨雷斯·桑切斯

“ IsSecuritySafeCritical”:false,“ IsSecurityTransparent”:false,“ MethodHandle”:{“ Value”:{“ value”:140716810003120}},“ Attributes”:150,“ CallingConvention”:1,“ ReturnType”:“ System.Void ,System.Private.CoreLib,版本= 4.0.0.0,文化=中性,PublicKeyToken = 7cec85d7bea7798e“,” ReturnTypeCustomAttributes“:{” ParameterType“:” System.Void,System.Private.CoreLib,版本= 4.0.0.0,文化=中性,PublicKeyToken = 7cec85d7bea7798e“,”名称“:null,” HasDefaultValue“:true,” DefaultValue“:null,” RawDefaultValue“:null,” MetadataToken“:134217728,”属性“:0,”位置“:-1, “ IsIn”:false,“ IsLcid”:false ,。...等

36

如果使用ASP.NET Core MVC,请将其添加到startup.cs文件的ConfigureServices方法中:

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

2
我已经确认此解决方案也可用于WebAPI EntityFramework Core 2.0
cesar-

13

这可能对您有帮助。

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
如果您还使用异步方法,则这是最好的方法。这可能是一个真正的痛苦,但是它解决了您本来会遇到的许多问题(包括此问题),并且由于只查询要使用的内容而性能更高。
Josh McKearin

在您的xyz.edmx中,打开xyz.Context.vb文件,该文件默认情况下是隐藏的。这将具有 codePublic Sub New()Mybase.New(“ name = EntityConName”)End Sub code。现在在End Sub之前添加 codeMe.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code 这将摆脱webapi的json输出中的“自引用循环”错误。
Venkat

我发现这对我不起作用。我使用了AsNoTracking()并对其进行了修复。也许可以帮助别人
scottsanpedro

@scottsanpedro,如果我们能看到您的代码,那就更好了。
ddagsan

6

您必须设置保留对象引用:

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

然后var q = (from a in db.Events where a.Active select a).ToList();像这样调用您的查询

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

请参阅:https//www.newtonsoft.com/json/help/html/PreserveObjectReferences.htm


4

将“ [JsonIgnore]”添加到模型类

{
  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

我正在使用Dot.Net Core 3.1并进行了搜索

“ Newtonsoft.Json.JsonSerializationException:为属性检测到自引用循环”

我将此添加到此问题中,因为这将很容易参考。您应该在Startup.cs文件中使用以下命令:

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

2

对于asp.net core 3.1.3这对我有用

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

1

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


6
尽管此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的其他上下文,可以改善其长期价值。
Alex Riabov

1

有时会出现循环,因为类型类对其他类有引用,而这些类对类型类有引用,因此您必须在json字符串中准确选择所需的参数,例如此代码。

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.