Json.net设置JsonSerializerSettings仍出现循环引用异常求助
解决潜在循环引用导致的JSON序列化崩溃问题
哥们儿,我之前也踩过类似的潜在循环引用导致序列化崩溃的坑,给你几个实际用过的排查和解决思路:
先搞清楚到底有没有隐藏的双向引用
有时候我们以为只是“潜在”循环,但实际上对象之间已经形成了双向引用链,只是序列化到一半崩溃了,没输出完整JSON而已。你可以用调试工具确认:
- 在Visual Studio的即时窗口里敲这段代码,看看能不能拿到值:
如果能返回数字,说明这俩类之间确实是双向引用,只是你之前没注意到。product.ProductPropertyValues.First().PropertyValue.ProductPropertyValues?.Count
检查你的配置是不是真的生效了
很多时候改了JsonSerializerSettings但没用,是因为序列化的时候没传这个配置!比如你是不是写了:
// 错误:用了默认配置,你的自定义settings根本没生效 var json = JsonConvert.SerializeObject(product);
正确的写法应该是把自定义配置传进去:
var settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, PreserveReferencesHandling = PreserveReferencesHandling.None }; var json = JsonConvert.SerializeObject(product, settings);
针对性解决办法
方法1:用[JsonIgnore]直接切断循环链
如果确认是双向引用,直接在其中一个类的反向引用属性上加[JsonIgnore],简单粗暴但有效:
public class PropertyValue { // 忽略这条反向引用,序列化时就不会走这个链了 [JsonIgnore] public ICollection<ProductPropertyValue> ProductPropertyValues { get; set; } }
这种方法比全局配置更精准,适合你这种“潜在循环”的场景,直接把可能出问题的引用排除在外。
方法2:自定义ContractResolver(不修改实体类)
如果实体类不能改(比如是第三方库的类),可以写个自定义的解析器来动态忽略指定属性:
public class IgnoreLoopResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); // 忽略PropertyValue里的ProductPropertyValues属性 if (member.DeclaringType == typeof(PropertyValue) && member.Name == nameof(PropertyValue.ProductPropertyValues)) { property.Ignored = true; } return property; } } // 使用的时候把解析器加到配置里 var settings = new JsonSerializerSettings { ContractResolver = new IgnoreLoopResolver() }; var json = JsonConvert.SerializeObject(product, settings);
方法3:分步序列化排查崩溃点
如果崩溃发生在序列化过程中,你可以先把对象转成JObject,逐个检查属性,定位到底是哪个属性搞的鬼:
var jObj = JObject.FromObject(product); // 逐个打印属性,比如先看ProductPropertyValues Console.WriteLine(jObj["ProductPropertyValues"]);
这样能帮你精准定位到触发崩溃的那个引用链。
额外提醒:注意序列化库的区别
如果你用的是.NET Core/.NET 5+的System.Text.Json,配置方式和Newtonsoft.Json不一样,别搞混了:
var options = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles }; var json = JsonSerializer.Serialize(product, options);
内容的提问来源于stack exchange,提问作者Fester
相关产品推荐
相关产品推荐

