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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:20:30