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

嵌套对象序列化求助:.NET循环引用对象序列化失败

嵌套对象序列化问题的解决思路

你的代码存在两个核心问题导致序列化失败:对象循环引用和WPF控件Ellipse无法被默认序列化,以下是具体解决步骤:

一、先明确问题根源

  1. 循环引用:对象链形成闭环(CSheet→CElement→CConnector→CElement→CSheet),默认序列化器会陷入无限递归。
  2. UI控件序列化限制:Ellipse是WPF的UI元素,包含大量不可序列化的内部状态,默认System.Text.Json无法处理这类复杂控件。

二、分步解决

1. 修复循环引用处理

你之前尝试的ReferenceHandler.IgnoreCycles是正确方向,但需要确保配置生效,同时结合Ellipse的处理才能完成序列化:

private void Serializacja_Click(object sender, RoutedEventArgs e)
{
    JsonSerializerOptions options = new JsonSerializerOptions()
    {
        ReferenceHandler = ReferenceHandler.IgnoreCycles,
        WriteIndented = true,
        // 确保可访问所有需要序列化的属性
        IgnoreReadOnlyProperties = false
    };
    // 后续添加Ellipse的处理逻辑后,再执行序列化
    string sheetstring = JsonSerializer.Serialize(sheet, options);
    // 可输出到文件验证结果
    File.WriteAllText("sheet.json", sheetstring);
}

2. 处理Ellipse的序列化问题

由于Ellipse作为UI控件不适合直接序列化,推荐两种方案:

方案A:直接忽略Ellipse属性

如果不需要保存UI控件状态,给CConnector的Circle属性添加[JsonIgnore]特性,跳过序列化:

using System.Text.Json.Serialization;

namespace serjalizacja
{
    public class CConnector
    {
        private Ellipse _circle;
        private string _name;
        private CElement _parent;

        [JsonIgnore] // 标记为忽略序列化
        public Ellipse Circle
        {
            get { return _circle; }
            set { _circle = value; }
        }

        // 其他属性、构造函数保持不变
    }
}

方案B:自定义转换器序列化关键属性

如果需要保存Ellipse的核心信息(如尺寸、颜色),可以创建自定义转换器,只序列化必要字段:

using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Shapes;
using System.Windows.Media;

public class EllipseConverter : JsonConverter<Ellipse>
{
    // 反序列化时还原Ellipse(按需实现)
    public override Ellipse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var ellipse = new Ellipse();
        
        if (root.TryGetProperty("Width", out var width))
            ellipse.Width = width.GetDouble();
        if (root.TryGetProperty("Height", out var height))
            ellipse.Height = height.GetDouble();
        if (root.TryGetProperty("FillColor", out var colorHex))
            ellipse.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorHex.GetString()));
        
        return ellipse;
    }

    // 序列化时只输出需要的属性
    public override void Write(Utf8JsonWriter writer, Ellipse value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteNumber("Width", value.Width);
        writer.WriteNumber("Height", value.Height);
        if (value.Fill is SolidColorBrush brush)
            writer.WriteString("FillColor", brush.Color.ToString());
        writer.WriteEndObject();
    }
}

然后在序列化选项中注册转换器:

JsonSerializerOptions options = new JsonSerializerOptions()
{
    ReferenceHandler = ReferenceHandler.IgnoreCycles,
    WriteIndented = true,
    Converters = { new EllipseConverter() } // 添加自定义转换器
};

3. 额外注意事项

  • 确保所有需要序列化的类都有无参构造函数(你的代码已经满足,可避免反序列化报错)。
  • 若需更精细控制,可给属性添加[JsonPropertyName]特性指定序列化后的键名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:18:13