【问题标题】:JSON.Net Self referencing loop detected检测到 JSON.Net 自引用循环
【发布时间】:2012-11-10 16:54:08
【问题描述】:

我的网站有一个 mssql 数据库,包含 4 个表。

当我使用这个时:

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]”。

【问题讨论】:

标签: c# serialization json.net


【解决方案1】:

我刚刚遇到了与父/子集合相同的问题,并发现该帖子解决了我的问题。 我只想显示父集合项的列表,不需要任何子数据,因此我使用了以下内容并且效果很好:

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

JSON.NET Error Self referencing loop detected for type

它还引用了 Json.NET codeplex 页面:

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

文档:ReferenceLoopHandling setting

【讨论】:

  • 视情况而定,您也可以使用PreserveReferencesHandling = PreserveReferencesHandling.Objects;,如下所述:solve-self-referencing-loop-issue-when-using-newtonsoft-json
  • 在 WebAPI OData v4 中,我发现某些类型的数据同时需要 ReferenceLoopHandling.Ignore 和 PreserveReferencesHandling.Objects
  • Allelluiah 非常感谢,仅投票 1 是不够的
  • 为我在 Blazor 服务器上的 Entity Framework Core 工作。
  • 谢谢!对于我的项目,我决定将其作为配置包含在我的 startup.cs 中。
【解决方案2】:

解决方法是忽略循环引用而不是序列化它们。此行为在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

【讨论】:

  • 用这个序列化对我来说需要很长时间
  • 当具有循环循环的对象是 NHibernate 模型 POCO 时,这似乎不起作用(在这种情况下,序列化检索大量垃圾,或者有时只是超时)。
  • "IsSecuritySafeCritical":false,"IsSecurityTransparent":false, "MethodHandle":{"Value":{"value":140716810003120}},"Attributes":150,"CallingConvention":1, “ReturnType”:“System.Void,System.Private.CoreLib,版本=4.0.0.0,Culture=neutral,PublicKeyToken=7cec85d7bea7798e”,“ReturnTypeCustomAttributes”:{“ParameterType”:“System.Void,System.Private.CoreLib,版本=4.0.0.0,文化=中性,PublicKeyToken=7cec85d7bea7798e","Name":null, "HasDefaultValue":true,"DefaultValue":null,"RawDefaultValue":null,"MetadataToken":134217728,"Attributes":0 “位置”:-1,“IsIn”:假,“IsLcid”:假,。 ...等
【解决方案3】:

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

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

【讨论】:

  • 我已经确认此解决方案也适用于 WebAPI EntityFramework Core 2.0
【解决方案4】:

这可能会对你有所帮助。

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

【讨论】:

  • 如果您还使用异步方法,这是处理它的最佳方法。这可能是一个真正的痛苦,但它解决了很多您本来会遇到的问题(包括这个问题),并且还可以提高性能,因为您只查询您将使用的内容。
  • 在您的 xyz.edmx 中,打开默认隐藏的 xyz.Context.vb 文件。这将有 code Public Sub New() Mybase.New("name=EntityConName") End Sub code。现在在 End Sub 之前添加 code Me.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code 这将消除 webapi 的 json 输出中的“自引用循环”错误。
  • 我发现这对我不起作用。我使用了 AsNoTracking() 并修复了它。也许帮助别人
  • @scottsanpedro 如果我们能看到你的代码就更好了。
【解决方案5】:

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

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

然后调用你的查询var q = (from a in db.Events where a.Active select a).ToList();like

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

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

【讨论】:

    【解决方案6】:

    我正在使用 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;
                    });
    

    【讨论】:

    • 为我在 Blazor 服务器上的 Entity Framework Core 工作。 – David Jones 刚刚编辑删除
    【解决方案7】:

    将“[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; }
    }
    

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        【解决方案9】:

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

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
        【解决方案10】:

        有时你有循环,因为你的类型类引用了其他类,而这些类引用了你的类型类,因此你必须在 json 字符串中选择你需要的参数,就像这段代码一样。

        List<ROficina> oficinas = new List<ROficina>();
        oficinas = /*list content*/;
        var x = JsonConvert.SerializeObject(oficinas.Select(o => new
                    {
                        o.IdOficina,
                        o.Nombre
                    }));
        

        【讨论】:

          【解决方案11】:

          JsonSerializer 实例可以配置为忽略引用循环。如下所示,此函数允许使用 json 序列化对象的内容保存文件:

              public static void SaveJson<T>(this T obj, string FileName)
              {
             
                 JsonSerializer serializer = new JsonSerializer();
                  serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                  using (StreamWriter sw = new StreamWriter(FileName))
                  {
                      using (JsonWriter writer = new JsonTextWriter(sw))
                      {
                          writer.Formatting = Formatting.Indented;
                          serializer.Serialize(writer, obj);
                      }
                  }
              }
          

          【讨论】:

            猜你喜欢
            • 2017-03-21
            • 2017-02-13
            • 2016-09-15
            • 2016-02-15
            • 2014-02-05
            • 1970-01-01
            • 1970-01-01
            • 2020-03-29
            相关资源
            最近更新 更多