JsonException: обнаружен возможный цикл объекта, который не поддерживается. Это может быть связано с циклом или если глубина объекта превышает - PullRequest
2 голосов
/ 13 февраля 2020

В моем веб-интерфейсе API при запуске проекта для получения данных из базы данных появилась эта ошибка. net core 3.1

JsonException: обнаружен возможный цикл объекта, который не поддерживается. Это может произойти из-за цикла или если глубина объекта превышает максимально допустимую глубину 32.

Это мой код my Model

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

my productCategory class это:

 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 project и помещаю этот URL: https://localhost: 44397 / api / products Я получил эту ошибку, я не могу ее исправить

Ответы [ 2 ]

4 голосов
/ 13 февраля 2020

это происходит потому, что ваши данные имеют ссылку l oop.

например

// 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 ...

Вы не можете обработать эталонную ситуацию l oop в новой System.Text.Json пока (netcore 3.1.1), если вы полностью не игнорируете ссылку, и это не всегда хорошая идея. (используя атрибут [JsonIgnore])

, но у вас есть два варианта, чтобы это исправить.

  1. вы можете использовать Newtonsoft.Json в вашем проекте вместо System.Text.Json (я связал для вас статью)

  2. Загрузите System.Text.Json версию пакета предварительного просмотра 5.0.0-alpha.1.20071.1 из галереи dotnet5 (через клиент NuGet в Visual Studio):

вариант 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.

но если вы решили просто игнорировать одну ссылку, используйте [JsonIgnore] для одного из этих свойств. но это приводит к нулевому результату в вашем ответе API для этого поля, даже если у вас нет ссылки l oop.

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;}
}
1 голос
/ 13 февраля 2020

Убедитесь, что у вас есть [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 и сначала код для определения вашей БД)

...