![](/img/trans.png)
[英]A possible object cycle was detected. This can be due to a cycle or if the object depth is larger than the maximum allowed depth of 32
[英]JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than
在我的 web api 中,當我運行項目以從數據庫獲取數據時出現此錯誤 .net core 3.1
JsonException: 檢測到不支持的可能的對象循環。 這可能是由於循環或對象深度大於最大允許深度 32。
這些是我的代碼我的模型
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string ProductText { get; set; }
public int ProductCategoryId { get; set; }
[JsonIgnore]
public virtual ProductCategory ProductCategory { get; set; }
}
我的 productCategory 類是:
public class ProductCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string CatText { get; set; }
public string ImagePath { get; set; }
public int Priority { get; set; }
public int Viewd { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ModifyDate { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
我的回購是
public async Task<IList<Product>> GetAllProductAsync()
{
return await _context.Products.Include(p => p.ProductCategory).ToListAsync();
}
我的界面
public interface IProductRepository
{
...
Task<IList<Product>> GetAllProductAsync();
...
}
這是我在 api 項目中的控制器
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly IProductRepository _productRepository;
public ProductsController(IProductRepository productRepository)
{
_productRepository = productRepository;
}
[HttpGet]
public ActionResult Get()
{
return Ok(_productRepository.GetAllProduct());
}
}
當我運行 api 項目並輸入這個 url: https://localhost:44397/api/products我得到那個錯誤,我無法解決它
發生這種情況是因為您的數據有一個參考循環。
例如
// this example creates a reference loop
var p = new Product()
{
ProductCategory = new ProductCategory()
{ products = new List<Product>() }
};
p.ProductCategory.products.Add(p); // <- this create the loop
var x = JsonSerializer.Serialize(p); // A possible object cycle was detected ...
您還不能在新的System.Text.Json
(netcore 3.1.1)中處理引用循環情況,除非您完全忽略引用並且它始終不是一個好主意。 (使用[JsonIgnore]
屬性)
但是你有兩個選擇來解決這個問題。
你可以在你的項目中使用Newtonsoft.Json
而不是System.Text.Json
(我為你鏈接了一篇文章)
從 dotnet5 庫(通過 Visual Studio 的 NuGet 客戶端)下載System.Text.Json
預覽包版本5.0.0-alpha.1.20071.1
:
選項 1 用法:
services.AddMvc()
.AddNewtonsoftJson(
options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
// if you not using .AddMvc use these methods instead
//services.AddControllers().AddNewtonsoftJson(...);
//services.AddControllersWithViews().AddNewtonsoftJson(...);
//services.AddRazorPages().AddNewtonsoftJson(...);
選項 2 用法:
// for manual serializer
var options = new JsonSerializerOptions
{
ReferenceHandling = ReferenceHandling.Preserve
};
string json = JsonSerializer.Serialize(objectWithLoops, options);
// -----------------------------------------
// for asp.net core 3.1 (globaly)
services.AddMvc()
.AddJsonOptions(o => {
o.JsonSerializerOptions
.ReferenceHandling = ReferenceHandling.Preserve
});
這些序列化程序具有ReferenceLoopHandling
功能。
ReferenceHandling
更改為ReferenceHandler
但是如果您決定忽略一個引用,請在這些屬性之一上使用[JsonIgnore]
。 但即使您沒有引用循環,它也會導致該字段的 API 響應為空結果。
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string ProductText { get; set; }
public int ProductCategoryId { get; set; }
// [JsonIgnore] HERE or
public virtual ProductCategory ProductCategory { get; set; }
}
public class ProductCategory
{
public int Id { get; set; }
// [JsonIgnore] or HERE
public ICollection<Product> products {get;set;}
}
我有同樣的問題,我的解決方法是添加 async 和 await 關鍵字,因為我在我的業務邏輯上調用 async 方法。
這是我的原始代碼:
[HttpGet]
public IActionResult Get()
{
//This is async method and I am not using await and async feature .NET which triggers the error
var results = _repository.GetAllDataAsync();
return Ok(results);
}
對此:
HttpGet]
public async Task<IActionResult> Get()
{
var results = await _repository.GetAllDataAsync();
return Ok(results);
}
確保在正確的字段上有 [JsonIgnore] 以避免循環引用。
在這種情況下,您將需要
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string ProductText { get; set; }
[JsonIgnore]
public virtual ProductCategory ProductCategory { get; set; }
}
您可能不需要 ProductCategoryId 字段(取決於您是否首先使用 EF 和代碼來定義您的數據庫)
編輯 - 回答noruk
在連接的對象和導航屬性中經常會出現混淆。 您可以在 JSON 中獲取所需的數據,還可以定義 EF 結構以獲取正確的數據庫結構(外鍵、索引等)。
舉這個簡單的例子。 產品(例如 T 恤)有多種尺寸或 SKU(例如小號、大號等)
public class Product
{
[Key]
[MaxLength(50)]
public string Style { get; set; }
[MaxLength(255)]
public string Description { get; set; }
public List<Sku> Skus { get; set; }
}
public class Sku
{
[Key]
[MaxLength(50)]
public string Sku { get; set; }
[MaxLength(50)]
public string Barcode { get; set; }
public string Size { get; set; }
public decimal Price { get; set; }
// One to Many for Product
[JsonIgnore]
public Product Product { get; set; }
}
您可以在此處序列化產品,JSON 數據將包括 SKU。 這是正常的做事方式。
但是,如果您序列化一個 SKU,您將不會獲得它的父產品。 包含導航屬性將使您進入可怕的循環並拋出“檢測到對象循環”錯誤。
我知道這在某些用例中是有限制的,但我建議您遵循這種模式,如果您希望父對象可用,您可以根據子對象單獨獲取它。
var parent = dbContext.SKUs.Include(p => p.Product).First(s => s.Sku == "MY SKU").Product
.NET 5 Web API
public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddControllers()
.AddJsonOptions(o => o.JsonSerializerOptions
.ReferenceHandler = ReferenceHandler.Preserve);
}
對於 net core 3.1,您必須在 Startup.cs 中添加:
services.AddMvc.AddJsonOptions(o => {
o.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
o.JsonSerializerOptions.MaxDepth = 0;
})
並使用 nuget.org 至少導入這個包,包括預發布:
<PackageReference Include="System.Text.Json" Version="5.0.0-rc.1.20451.14" />
最后用System.Text.Json修復了我的而不是NewtonSoft.Json使用
var options = new JsonSerializerOptions()
{
MaxDepth = 0,
IgnoreNullValues = true,
IgnoreReadOnlyProperties = true
};
使用選項進行序列化
objstr = JsonSerializer.Serialize(obj,options);
以下代碼在 dotnet 5.0 中對我有用:
services.AddControllersWithViews()
.AddJsonOptions(o => o.JsonSerializerOptions
.ReferenceHandler = ReferenceHandler.Preserve);
我的項目構建時出現了類似的錯誤。
這是之前的代碼
public class PrimaryClass {
public int PrimaryClassId
public ICollection<DependentClass> DependentClasses { get; set; }
}
public class DependentClass {
public int DependentClassId { get; set; }
public int PrimaryClassId { get; set; }
public PrimaryClass primaryClass { get; set; }
}
我從 DependentClass 模型中拿走了 PrimaryClass 對象。
代碼之后
public class PrimaryClass {
public int PrimaryClassId
public ICollection<DependentClass> DependentClasses { get; set; }
}
public class DependentClass {
public int DependentClassId { get; set; }
public int PrimaryClassId { get; set; }
}
我還必須調整OnModelCreating
方法
modelBuilder.Entity<PrimaryClass>().HasMany(p => p.DependentClasses).WithOne(d => d.primaryClass).HasForeignKey(d => d.PrimaryClassId);
到
modelBuilder.Entity<PrimaryClass>().HasMany(p => p.DependentClasses);
正在運行的 DbSet 查詢是
public async Task<List<DependentClass>> GetPrimaryClassDependentClasses(PrimaryClass p)
{
return await _dbContext.DependentClass.Where(dep => dep.PrimaryClassId == p.PrimaryClassId).ToListAsync();
}
錯誤可能與這 3 段代碼中的任何一段有關,但是從依賴類中刪除主要對象引用並調整OnModelCreating
解決了錯誤,我只是不確定為什么會導致循環。
就我而言,問題在於創建實體關系時。 我像這樣在依賴實體中使用外鍵鏈接主實體
[ForeignKey("category_id")]
public Device_Category Device_Category { get; set; }
我還提到了主實體中的 dippendend 實體。
public List<Device> devices { get; set; }
這創造了一個循環。
依賴實體
public class Device
{
[Key]
public int id { get; set; }
public int asset_number { get; set; }
public string brand { get; set; }
public string model_name { get; set; }
public string model_no { get; set; }
public string serial_no { get; set; }
public string os { get; set; }
public string os_version { get; set; }
public string note { get; set; }
public bool shared { get; set; }
public int week_limit { get; set; }
public bool auto_acceptance { get; set; }
public bool booking_availability { get; set; }
public bool hide_device { get; set; }
public bool last_booked_id { get; set; }
//getting the relationships category 1 to many
public int category_id { get; set; }
[ForeignKey("category_id")]
public Device_Category Device_Category { get; set; }
public List<Booking> Bookings { get; set; }
}
主要實體
public class Device_Category
{
public int id { get; set; }
public string name { get; set; }
public List<Device> devices { get; set; }
}
}
所以我評論了
public List<Device> devices { get; set; }
內部主要實體(Device_Category)和問題解決
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.