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

时间:2011-09-13 05:25:26

标签: json serialization json.net

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

JsonConvert.SerializeObject 

我收到以下错误:

  

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

如何解决这个问题?

26 个答案:

答案 0 :(得分:417)

使用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/

答案 1 :(得分:392)

那是最好的解决方案 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:忽略并保留参考属性

此修复是模型类上的decorate属性,用于控制模型或属性级别的序列化行为。要忽略该属性:

 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序列化程序,并对模型类提供更多控制。

答案 2 :(得分:47)

修复是忽略循环引用而不是序列化它们。此行为在JsonSerializerSettings

中指定 带有重载的

JsonConvert

JsonConvert.SerializeObject(YourObject, 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 :(得分:38)

最简单的方法是从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; }

虽然现在,我创建的模型只包含我想要传递的属性,因此它更轻,不包含不需要的集合,并且在重建生成的文件时我不会丢失更改...

答案 4 :(得分: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));
        });
    }

答案 5 :(得分:7)

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

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

答案 6 :(得分:5)

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

https://docs.microsoft.com/en-us/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
    );

...
}

答案 7 :(得分:5)

要在循环问题时序列化使用NEWTONSOFTJSON,在我的情况下我不需要修改global.asax或者apiconfig。我只是使用JsonSerializesSettings忽略循环处理。

pthread_mutex_destroy

答案 8 :(得分:4)

您也可以将属性应用于该属性。 [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

答案 9 :(得分: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);
        });
    }

答案 10 :(得分:2)

我有这个例外,我的工作解决方案简单易用,

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

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

反序列化时重置属性:

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

使用Newtonsoft.Json;

答案 11 :(得分:2)

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

我刚把它添加到我的基础存储库中:

context.Configuration.ProxyCreationEnabled = false;

“context”对象是我在基本存储库中使用的构造函数参数,因为我使用了依赖注入。您可以在实例化datacontext的任何地方更改ProxyCreationEnabled属性。

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

答案 12 :(得分:2)

WebApiConfig.cs类:

中使用此功能
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

答案 13 :(得分:1)

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

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

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

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

答案 14 :(得分:1)

团队:

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

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

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

答案 15 :(得分:1)

对于.NET Core 3.0,如下所示更新Startup.cs类。

public void ConfigureServices(IServiceCollection services)
{
...

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

...
}

请参阅:https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-5/

答案 16 :(得分:1)

只需更新 Startup.cs 文件中的 services.AddControllers()

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

答案 17 :(得分:0)

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

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

答案 18 :(得分:0)

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

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

答案 19 :(得分:0)

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

答案 20 :(得分: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; }

}

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

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

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

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

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

预期的行为应该是

嘿,EfCore能否也将“ 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,以避免自引用循环甚至数组。

Expression Builder

    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并排除我不想要的属性!

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

答案 21 :(得分:0)

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

答案 22 :(得分:0)

我继承了一个数据库应用程序,该应用程序将数据模型提供给网页。默认情况下,序列化将尝试遍历整个模型树,此处的大多数答案是如何防止这种情况的一个好的开始。

尚未探索的一个选项是使用界面来提供帮助。我将从先前的示例中窃取:

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 interface IgnoreUser
{
    [JsonIgnore]
    User User { get; set; }
}

public interface IgnoreCompany
{
    [JsonIgnore]
    User User { get; set; }
}

public partial class CompanyUser : IgnoreUser, IgnoreCompany
{
}

在上述解决方案中,没有Json设置受到损害。将LazyLoadingEnabled和/或ProxyCreationEnabled设置为false会影响您的所有后端编码,并阻止ORM工具的某些真正好处。根据您的应用程序,LazyLoading / ProxyCreation设置可以阻止在不手动加载导航属性的情况下加载它们。

这是防止导航属性序列化的更好得多的解决方案,它使用标准的json功能: How can I do JSON serializer ignore navigation properties?

答案 23 :(得分:0)

在 .Net 5.x 中,使用以下代码更新 startup.cs 中的 ConfigureServices 方法

public void ConfigureServices(IServiceCollection services)
{
    ----------------
    ----------------
    services.AddMvc().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
    });
    ------------------
}

默认情况下,序列化(System.Text.Json.Serialization)不支持带循环的对象,也不保留重复引用。使用 Preserve 在序列化和元数据消耗时启用唯一对象引用保留,以读取反序列化时保留的引用。 MSDN Link

答案 24 :(得分:-1)

对于不循环这对我有用 - ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

我在这里解决了所有问题 - 使用.Net Core 2 WebAPI进行实体框架子级序列化 https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606

欢迎任何评论。 也许有人可以在某个时候使用它。

答案 25 :(得分:-2)

我喜欢Application_Start()中的解决方案,如答案here

显然我无法使用我的函数中的配置访问JavaScript中的json对象,就像DalSoft的回答一样,因为返回的对象有&#34; \ n \ r&#34;遍布对象的(key,val)。

无论如何,无论哪种工作都很棒(因为根据所提出的评论和问题,不同的方法可以在不同的场景中工作),尽管采用标准的方法来支持这种方法会更好。