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


494

我尝试序列化从实体数据模型.edmx和使用时自动生成的POCO类

JsonConvert.SerializeObject 

我收到以下错误:

错误检测到类型为System.data.entity的自引用循环。

我该如何解决这个问题?



当您使用LINQ和MVC:stackoverflow.com/a/38241856
插件

使用.NET Core 2时:stackoverflow.com/a/48709134/4496145
Dave

2
当我想序列化async方法调用(a Task)的结果而忘记为await语句加上前缀时,发生了此错误。
Uwe Keim

Answers:


485

那是最好的解决方案 https://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

修复1:全局忽略循环引用

(我选择/尝试了这个,还有很多其他选择)

json.net序列化程序可以忽略循环引用。将以下代码放入WebApiConfig.cs文件中:

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

简单的修复将使序列化程序忽略引用,这将导致循环。但是,它有局限性:

  • 数据丢失循环参考信息
  • 该修复仅适用于JSON.net
  • 如果引用链很深,则无法控制引用级别

如果要在非API ASP.NET项目中使用此修复程序,可以将上述行添加到中Global.asax.cs,但首先添加:

var config = GlobalConfiguration.Configuration;

如果要在.Net Core项目中使用此功能,可以更改Startup.cs为:

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

修复2:全局保留循环引用

此第二个修复程序类似于第一个。只需将代码更改为:

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

应用此设置后,数据形状将更改。

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

$ id和$ ref保持所有引用并使对象图级别平坦,但是客户端代码需要知道形状变化以使用数据,并且它仅适用于JSON.NET序列化器。

修复3:忽略并保留引用属性

此修复程序修饰模型类上的属性,以控制模型或属性级别上的序列化行为。要忽略该属性:

 public class Category 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 

        [JsonIgnore] 
        [IgnoreDataMember] 
        public virtual ICollection<Product> Products { get; set; } 
    } 

JsonIgnore用于JSON.NET,而IgnoreDataMember用于XmlDCSerializer。要保留参考:

 // Fix 3 
        [JsonObject(IsReference = true)] 
        public class Category 
        { 
            public int Id { get; set; } 
            public string Name { get; set; } 

           // Fix 3 
           //[JsonIgnore] 
           //[IgnoreDataMember] 
           public virtual ICollection<Product> Products { get; set; } 
       } 

       [DataContract(IsReference = true)] 
       public class Product 
       { 
           [Key] 
           public int Id { get; set; } 

           [DataMember] 
           public string Name { get; set; } 

           [DataMember] 
           public virtual Category Category { get; set; } 
       }

JsonObject(IsReference = true)]用于JSON.NET和[DataContract(IsReference = true)]XmlDCSerializer。注意:DataContract在类上应用后,您需要添加DataMember到要序列化的属性。

这些属性可以同时应用于json和xml序列化程序,并提供对模型类的更多控制。


7
Fix 3对我有用。只需删除DataContract和DataMember属性,然后将JsonObject(IsReference = true)放在DTO上即可。而且有效。谢谢。
大师

1
试试这个GlobalConfiguration.Configuration
Bishoy Hanna 2014年

1
修复3的优点是它可以在没有GlobalConfiguration的客户端代码上工作
dumbledad

1
@BishoyHanna,您可以编辑您的答案以允许它在普通的ASP.NET应用程序中使用吗?您可以使用我建议的编辑:stackoverflow.com/review/suggested-edits/17797683
NH。

2
使用[JsonIgnore]上面的属性对我有用。
内森·贝克

467

使用JsonSerializerSettings

  • ReferenceLoopHandling.Error(默认)如果遇到参考循环将出错。这就是为什么您会例外。
  • ReferenceLoopHandling.Serialize 如果对象是嵌套的但不是无限期的,则很有用。
  • ReferenceLoopHandling.Ignore 如果对象本身是子对象,则不会序列化该对象。

例:

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

如果必须序列化无限期嵌套的对象,则可以使用PreserveObjectReferences来避免StackOverflowException。

例:

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

选择对您要序列化的对象有意义的对象。

参考http://james.newtonking.com/json/help/


66
序列化数据表时遇到错误。我用ReferenceLoopHandling = ReferenceLoopHandling.Ignore它来工作

8
如果数据中存在引用循环,则使用ReferenceLoopHandling.Serialize会导致序列化器进入无限递归循环并溢出堆栈。
Brian Rogers 2014年

1
正确。由于问题是关于EF模型,因此也是一个有效的关注点。修改为提供所有可用选项。
DalSoft 2014年

1
我遇到同样的错误试图序列化一个对象的时候......然而,对象没有比枚举类型以外的任何引用..
马林

1
对我而言,EF是导致此问题的主要原因,因为自引用的实体无处不在。
Teoman shipahi 2015年

57

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

JsonConvert重载:

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

使用Application_Start()Global.asax.cs中的代码进行全局设置

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

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


为什么在进行全局设置时将格式设置为缩进格式?
Murphybro2

绝对是我们解决此问题所需要的(在部署过程中发现)!你这个家伙。...感谢您为我们节省了时间!!
瑞安·伊斯塔布鲁克

我通过在类“ Startup.cs”中添加“ JsonConvert.DefaultSettings” =()=>新的JsonSerializerSettings {....}来解决我的问题
Beldi Anouar

45

最简单的方法是从nuget 安装Json.NET ,并将[JsonIgnore]属性添加到类中的虚拟属性,例如:

    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> Project_ID { get; set; }

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

尽管这些天来,我创建的模型只包含我要传递的属性,因此它比较轻巧,不包含不需要的集合,并且在重建生成的文件时不会丢失更改...


3
使用牛顿JSON的最佳答案
Aizen

21

在.NET Core 1.0中,可以在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<char>.Shared));
        });
    }

但是在这种情况下,如果我想知道此属性被忽略,那么我将不会有任何异常。
Mayer Spitzer

10

如果您使用的是.NET Core 2.x,请更新Startup.cs中的ConfigureServices部分

https://docs.microsoft.com/zh-cn/ef/core/querying/related-data#related-data-and-serialization

    public void ConfigureServices(IServiceCollection services)
    {
    ...

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

    ...
    }

如果您使用的是不带MVC的.NET Core 3.x,则可能是:

services.AddControllers()
  .AddNewtonsoftJson(options =>
      options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
   );

如果您使用的是Entity Framework和数据库优先设计模式,则此参考循环处理几乎是必需的。


2
如果我不使用services.AddMvc()怎么办?
prisar

2
这是不好的做法吗?
Renan Coelho

乍一看,您可能会认为这是一个不好的做法,因为它可能会覆盖避免避免旧的“无限循环”问题的“有意设计”。但是,如果考虑类的用例,则可能需要它们互相引用。例如,您可能要访问“树”>“水果”和“水果”>“树”。
Dave Skender

另外,如果您将数据库优先的设计模式与Entity Framework等一起使用,则根据您在数据库中设置外键的方式,它将自动创建这些循环引用,因此如果您要使用此设置,则几乎必须使用此设置。对您的课程进行反向工程。
Dave Skender

9

在发生循环问题时,要在NEWTONSOFTJSON中序列化我们,就我而言,我不需要修改global.asax或apiconfig。我只是使用JsonSerializesSettings忽略了循环处理。

JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var lst = db.shCards.Where(m => m.CardID == id).ToList();
string json = JsonConvert.SerializeObject(lst, jss);

1
如果有人来这里让班轮在监视窗口中移动,以便可以在文本中搜索:Newtonsoft.Json.JsonConvert.SerializeObject(objToSerialize, new Newtonsoft.Json.JsonSerializerSettings() {ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore});
Graham

8

我们可以将这两行添加到DbContext类构造函数中以禁用自我引用循环,例如

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

这是最简单的一种,像吊饰一样工作。投票,非常感谢...
MuratYıldız18年

就像我在另一个问题中写的那样:我不喜欢这种答案,因为您要关闭默认启用的EF6功能,并且这段代码可能会破坏程序的其他部分。您应该解释它的作用及其产生的影响。
El Mac

@ElMac是正确的,但是如果我们不需要该功能,那么为什么不能使用此解决方案?
Sanjay Nishad '18年

@SanjayNishad我不介意您是否不需要该功能。它只是关于不知道他们正在禁用什么的用户。
El Mac

6

您也可以将属性应用于属性。该[JsonProperty( ReferenceLoopHandling = ... )]属性非常适合于此。

例如:

/// <summary>
/// Represents the exception information of an event
/// </summary>
public class ExceptionInfo
{
    // ...code omitted for brevity...

    /// <summary>
    /// An inner (nested) error.
    /// </summary>
    [JsonProperty( ReferenceLoopHandling = ReferenceLoopHandling.Ignore, IsReference = true )]
    public ExceptionInfo Inner { get; set; }

    // ...code omitted for brevity...    
}

希望有帮助,Jaans


4

要忽略循环引用而不在MVC 6中全局对其进行序列化,请在startup.cs中使用以下内容:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().Configure<MvcOptions>(options =>
        {
            options.OutputFormatters.RemoveTypesOf<JsonOutputFormatter>();
            var jsonOutputFormatter = new JsonOutputFormatter();
            jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            options.OutputFormatters.Insert(0, jsonOutputFormatter);
        });
    }

2

WebApiConfig.cs课堂上使用这个:

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

2

对我来说,我不得不走另一条路。不必尝试修复JSON.Net序列化程序,我必须在datacontext上进行延迟加载之后。

我刚刚将其添加到我的基本存储库中:

context.Configuration.ProxyCreationEnabled = false;

因为我使用依赖项注入,所以“上下文”对象是我在基础存储库中使用的构造函数参数。您可以在实例化数据上下文的任何位置更改ProxyCreationEnabled属性。

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


2

我有这个例外,并且我的工作解决方案很简单,

通过向其添加JsonIgnore属性来忽略Referenced属性:

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

反序列化时重置属性:

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

使用Newtonsoft.Json;


这是我需要的魔术。解决问题[JsonIgnore]
saviour123 '18

2

球队:

这适用于ASP.NET Core。上面的挑战是如何“设置忽略设置”。根据您设置应用程序的方式,这可能会非常具有挑战性。这对我有用。

可以将其放在您的公共void ConfigureServices(IServiceCollection服务)部分中。

services.AddMvc().AddJsonOptions(opt => 
        { 
      opt.SerializerSettings.ReferenceLoopHandling =
      Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

2

人们已经谈论过[JsonIgnore]被添加到类的虚拟属性中,例如:

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

我还将共享另一个选项[JsonProperty(NullValueHandling = NullValueHandling.Ignore)],该选项仅在属性为null时才将其从序列化中删除:

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


0

只需放置Configuration.ProxyCreationEnabled = false;在上下文文件中即可;这将解决问题。

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

0

使用自定义配置JsonSerializerSettings解决了我的问题:

services.AddMvc(
  // ...
               ).AddJsonOptions(opt =>
                 {
                opt.SerializerSettings.ReferenceLoopHandling =
                    Newtonsoft.Json.ReferenceLoopHandling.Serialize;
                opt.SerializerSettings.PreserveReferencesHandling =
                    Newtonsoft.Json.PreserveReferencesHandling.Objects;
                 });

0

还请确保在您的方法中使用等待和异步。如果您的对象未正确序列化,则会出现此错误。


0

我遇到了同样的问题,我尝试使用JsonSetting忽略自引用错误,这有点儿麻烦,直到我得到了一个非常自引用的类,并且我的dot-net进程挂在Json编写值上。

我的问题

    public partial class Company : BaseModel
{
    public Company()
    {
        CompanyUsers = new HashSet<CompanyUser>();
    }

    public string Name { get; set; }

    public virtual ICollection<CompanyUser> CompanyUsers { get; set; }
}

public partial class CompanyUser
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public int UserId { get; set; }

    public virtual Company Company { get; set; }

    public virtual User User { get; set; }
}

public partial class User : BaseModel
{
    public User()
    {
        CompanyUsers = new HashSet<CompanyUser>();
    }

    public string DisplayName { get; set; }
    public virtual ICollection<CompanyUser> CompanyUsers { get; set; }

}

您可以在引用CompanyUser的 User类中看到问题类,它是一个自引用。

现在,我正在调用包含所有关系属性的GetAll方法。

cs.GetAll("CompanyUsers", "CompanyUsers.User");

在此阶段,我的DotNetCore进程挂在执行JsonResult上,写入值...并永不结束。在我的Startup.cs中,我已经设置了JsonOption。由于某些原因,EFCore包含了我不要求Ef提供的嵌套属性。

    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

预期的行为应该是这样

嗨,EfCore您能否在我的Company类中也包含“ CompanyUsers”数据,以便我可以轻松访问这些数据。

然后

嗨,EfCore还可以同时包含“ CompanyUsers.User”数据,这样我就可以轻松访问像Company.CompanyUsers.First()。User.DisplayName这样的数据了 吗?

在此阶段,我应该只获得此“ Company.CompanyUsers.First()。User.DisplayName”,并且不应给我造成自我引用问题的Company.CompanyUsers.First()。User.CompanyUsers;从技术上讲,它不应该给我User.CompanyUsers,因为CompanyUsers是导航属性。但是,EfCore感到非常兴奋,并给了我User.CompanyUsers

因此,我决定编写一种扩展方法,以将属性从对象中排除(实际上不排除它只是将属性设置为null)。不仅如此,它还将对数组属性起作用。下面是我还将为其他用户导出nuget包的代码(不确定是否可以帮助某人)。原因很简单,因为我懒得写.Select(n => new {n.p1,n.p2}); 我只是不想编写select语句以仅排除1个属性!

这不是最好的代码(我会在某个阶段进行更新),因为我急忙编写,尽管这可能也有助于希望使用数组排除(设置null)对象的人。

    public static class PropertyExtensions
{
    public static void Exclude<T>(this T obj, Expression<Func<T, object>> expression)
    {
        var visitor = new PropertyVisitor<T>();
        visitor.Visit(expression.Body);
        visitor.Path.Reverse();
        List<MemberInfo> paths = visitor.Path;
        Action<List<MemberInfo>, object> act = null;

        int recursiveLevel = 0;
        act = (List<MemberInfo> vPath, object vObj) =>
        {

            // set last propert to null thats what we want to avoid the self-referencing error.
            if (recursiveLevel == vPath.Count - 1)
            {
                if (vObj == null) throw new ArgumentNullException("Object cannot be null");

                vObj.GetType().GetMethod($"set_{vPath.ElementAt(recursiveLevel).Name}").Invoke(vObj, new object[] { null });
                return;
            }

            var pi = vObj.GetType().GetProperty(vPath.ElementAt(recursiveLevel).Name);
            if (pi == null) return;
            var pv = pi.GetValue(vObj, null);
            if (pi.PropertyType.IsArray || pi.PropertyType.Name.Contains("HashSet`1") || pi.PropertyType.Name.Contains("ICollection`1"))
            {
                var ele = (IEnumerator)pv.GetType().GetMethod("GetEnumerator").Invoke(pv, null);

                while (ele.MoveNext())
                {
                    recursiveLevel++;
                    var arrItem = ele.Current;

                    act(vPath, arrItem);

                    recursiveLevel--;
                }

                if (recursiveLevel != 0) recursiveLevel--;
                return;
            }
            else
            {
                recursiveLevel++;
                act(vPath, pv);
            }

            if (recursiveLevel != 0) recursiveLevel--;

        };

        // check if the root level propert is array
        if (obj.GetType().IsArray)
        {
            var ele = (IEnumerator)obj.GetType().GetMethod("GetEnumerator").Invoke(obj, null);
            while (ele.MoveNext())
            {
                recursiveLevel = 0;
                var arrItem = ele.Current;

                act(paths, arrItem);
            }
        }
        else
        {
            recursiveLevel = 0;
            act(paths, obj);
        }

    }

    public static T Explode<T>(this T[] obj)
    {
        return obj.FirstOrDefault();
    }

    public static T Explode<T>(this ICollection<T> obj)
    {
        return obj.FirstOrDefault();
    }
}

上面的扩展类将使您能够将属性设置为null以避免自引用循环甚至数组。

表情生成器

    internal class PropertyVisitor<T> : ExpressionVisitor
{
    public readonly List<MemberInfo> Path = new List<MemberInfo>();

    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }


    protected override Expression VisitMember(MemberExpression node)
    {
        if (!(node.Member is PropertyInfo))
        {
            throw new ArgumentException("The path can only contain properties", nameof(node));
        }

        Path.Add(node.Member);
        return  base.VisitMember(node);
    }
}

用途:

模型类

    public class Person
{
    public string Name { get; set; }
    public Address AddressDetail { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public Country CountryDetail { get; set; }
    public Country[] CountryDetail2 { get; set; }
}

public class Country
{
    public string CountryName { get; set; }
    public Person[] CountryDetail { get; set; }
}

虚拟数据

           var p = new Person
        {
            Name = "Adeel Rizvi",
            AddressDetail = new Address
            {
                Street = "Sydney",
                CountryDetail = new Country
                {
                    CountryName = "AU"
                }
            }
        };

        var p1 = new Person
        {
            Name = "Adeel Rizvi",
            AddressDetail = new Address
            {
                Street = "Sydney",
                CountryDetail2 = new Country[]
                {
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },

                }
            }
        };

情况:

情况1:仅排除没有任何数组的属性

p.Exclude(n => n.AddressDetail.CountryDetail.CountryName);

情况2:排除具有1个数组的属性

p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryName);

情况3:排除具有2个嵌套数组的属性

p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryDetail.Explode().Name);

情况4:包含的EF GetAll查询

var query = cs.GetAll("CompanyUsers", "CompanyUsers.User").ToArray();
query.Exclude(n => n.Explode().CompanyUsers.Explode().User.CompanyUsers);
return query;

您已经注意到Explode()方法也是它的扩展方法,仅用于表达式构建器从数组属性获取属性。每当有数组属性时,请使用.Explode()。YourPropertyToExclude或.Explode()。Property1.MyArrayProperty.Explode()。MyStupidProperty。上面的代码帮助我避免了自我引用的深度。现在,我可以使用GetAll并排除我不想要的属性!

感谢您阅读这篇重要文章!



-1

C#代码:

            var jsonSerializerSettings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
            };

            var jsonString = JsonConvert.SerializeObject(object2Serialize, jsonSerializerSettings);

            var filePath = @"E:\json.json";

            File.WriteAllText(filePath, jsonString);

这基本上与八年前@DalSoft给予高度评价的答案中提供的指导相同,但解释却很少。
杰里米·卡尼

希望它将解决问题,但请在其中添加代码说明,以便用户完全理解他/她真正想要的。
Jaimil Patel

-2

我喜欢这里Application_Start()答案中的解决方案

显然,我无法使用DalSoft的答案中的函数来访问JavaScript中的json对象,因为返回的对象在对象的(键,val)上全部为“ \ n \ r”。

无论如何,任何有效的方法都是很棒的(因为基于所提出的评论和问题,不同的方法可以在不同的场景中工作),尽管最好的标准方法是使用一些支持该方法的好的文档。

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.