配置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
相关产品推荐
相关产品推荐

