关联数据和序列化

由于 EF Core 会自动修正导航属性,因此在对象图中可能会产生循环引用。 例如,加载博客及其关联文章会生成引用文章集合的博客对象。 其中每篇文章将返回引用该博客。

某些序列化框架不允许使用循环引用。 例如,Json.NET 在发现循环引用的情况下,会引发以下异常。

Newtonsoft.Json.JsonSerializationException:为“MyApplication.Models.Blog”类型的“Blog”属性检测到自引用循环。

如果发现循环,System.Text.Json 将引发类似的异常。

System.Text.Json.JsonException:检测到可能的对象循环。 这可能是由于循环造成的,或者是因为对象深度大于允许的最大深(即 32)。 请考虑在 JsonSerializerOptions 上使用 ReferenceHandler.Preserve 来支持循环。

如果使用的是 ASP.NET Core 中的 Json.NET,可以将 Json.NET 配置为忽略在对象图中找到的循环。 此配置是通过 Startup.cs 中的 ConfigureServices(...) 方法完成的。

public void ConfigureServices(IServiceCollection services)
{
    ...

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

    ...
}

如果使用 System.Text.Json,可按如下所示对其进行配置。

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
        });

    ...
}

另一种替代方法是忽略导致 JSON 序列化循环的导航属性。 如果使用 Json.NET,可以使用 [JsonIgnore] 特性修饰其中一个导航属性,该特性指示 Json.NET 在序列化时不遍历该导航属性。 对于 System.Text.Json,可以使用 System.Text.Json.Serialization 命名空间中的 [JsonIgnore] 特性来实现相同的效果。