You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置ReferenceHandler.Preserve仍遇Json循环引用错误,疑与IDistributedCache有关

解决IDistributedCache序列化时的Json循环引用问题

你的怀疑完全正确:IDistributedCache不会自动复用Controllers配置的Json序列化选项,因为控制器的AddJsonOptions是专门为ASP.NET Core的MVC管道(API响应、视图模型序列化)设计的,和分布式缓存的序列化逻辑属于完全独立的场景。

解决方案:单独配置分布式缓存的Json序列化规则

1. 手动传入序列化选项

直接创建带有ReferenceHandler.Preserve配置的JsonSerializerOptions实例,在调用SetAsync时显式序列化对象并传入:

// 定义缓存专用的序列化配置(可放在Program.cs或全局配置类中)
var cacheJsonOptions = new JsonSerializerOptions
{
    ReferenceHandler = ReferenceHandler.Preserve,
    // 可添加其他需要的配置,比如忽略null值、属性大小写匹配等
    IgnoreNullValues = true,
    PropertyNameCaseInsensitive = true
};

// 序列化对象并存入缓存
var serializedModel = JsonSerializer.Serialize(yourTargetModel, cacheJsonOptions);
await _distributedCache.SetStringAsync("your-cache-key", serializedModel);

// 读取缓存时也要用相同的配置反序列化
var cachedJson = await _distributedCache.GetStringAsync("your-cache-key");
var cachedModel = JsonSerializer.Deserialize<YourModelType>(cachedJson, cacheJsonOptions);

2. 封装扩展方法简化调用

为了避免重复编写序列化代码,可以给IDistributedCache封装扩展方法,内置预设的序列化选项:

public static class DistributedCacheJsonExtensions
{
    // 全局默认配置
    private static readonly JsonSerializerOptions _defaultJsonOptions = new()
    {
        ReferenceHandler = ReferenceHandler.Preserve,
        IgnoreNullValues = true
    };

    // 自定义SetAsync扩展
    public static async Task SetJsonAsync<T>(this IDistributedCache cache, string key, T value, DistributedCacheEntryOptions options = null, JsonSerializerOptions jsonOptions = null)
    {
        var json = JsonSerializer.Serialize(value, jsonOptions ?? _defaultJsonOptions);
        await cache.SetStringAsync(key, json, options);
    }

    // 自定义GetAsync扩展
    public static async Task<T> GetJsonAsync<T>(this IDistributedCache cache, string key, JsonSerializerOptions jsonOptions = null)
    {
        var json = await cache.GetStringAsync(key);
        return json == null ? default : JsonSerializer.Deserialize<T>(json, jsonOptions ?? _defaultJsonOptions);
    }
}

之后调用就会简洁很多:

// 存入缓存
await _distributedCache.SetJsonAsync("your-cache-key", yourTargetModel);

// 读取缓存
var cachedModel = await _distributedCache.GetJsonAsync<YourModelType>("your-cache-key");

3. 补充说明

  • 如果你不想使用ReferenceHandler.Preserve,继续用[JsonIgnore]标记导航属性也是可行的,但这种方式更适合固定不需要缓存的关联数据,灵活性不如全局配置序列化选项。
  • 若项目中使用的是Newtonsoft.Json而非System.Text.Json,只需将上述代码中的JsonSerializer替换为JsonConvert,对应的配置改为JsonSerializerSettings并设置PreserveReferencesHandling = PreserveReferencesHandling.Objects即可。

内容的提问来源于stack exchange,提问作者pinale

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:45:49