You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#自定义Label控件JSON序列化仅保留自定义属性问题

嘿,这个问题我太熟了!当你继承WinForms的Label控件做自定义控件时,序列化时总会带出基类一大堆没用的属性,要只保留自己加的X、Y、H、W,有几个实用的方案,我给你拆解清楚:

方案1:用Newtonsoft.Json(Json.NET)的特性精准控制

如果你项目里用的是Json.NET(这是很多.NET项目的标配),可以通过特性直接指定哪些属性要序列化:

首先在你的自定义Label类上标记[JsonObject(MemberSerialization.OptIn)],意思是“只序列化我明确标记的属性”,然后给每个自定义属性加上[JsonProperty]

using Newtonsoft.Json;
using System.Windows.Forms;

[JsonObject(MemberSerialization.OptIn)]
public class CustomLabel : Label
{
    [JsonProperty]
    public int X { get; set; }
    
    [JsonProperty]
    public int Y { get; set; }
    
    [JsonProperty]
    public int H { get; set; }
    
    [JsonProperty]
    public int W { get; set; }

    // 你的其他自定义逻辑...
}

之后序列化的时候直接用JsonConvert.SerializeObject(customLabel),出来的JSON就只会包含X、Y、H、W这四个属性,基类的那些比如TextFontBackColor之类的都会被自动过滤掉。

方案2:用System.Text.Json的两种方式(.NET Core/.NET 5+)

如果你的项目用的是微软官方的System.Text.Json,有两种简单的做法:

方式A:匿名类型快速序列化

如果你的自定义属性不多,直接创建一个包含目标属性的匿名类型再序列化,简单粗暴又高效:

using System.Text.Json;

var myCustomLabel = new CustomLabel { X = 10, Y = 20, H = 30, W = 40 };
var json = JsonSerializer.Serialize(new 
{ 
    myCustomLabel.X, 
    myCustomLabel.Y, 
    myCustomLabel.H, 
    myCustomLabel.W 
});

方式B:自定义转换器(适合属性多或需要重复使用的场景)

如果以后可能添加更多自定义属性,或者需要统一处理序列化逻辑,可以写一个自定义的Json转换器:

using System.Text.Json;
using System.Text.Json.Serialization;

public class CustomLabelConverter : JsonConverter<CustomLabel>
{
    // 反序列化逻辑(如果需要还原对象的话)
    public override CustomLabel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var label = new CustomLabel();
        using (var doc = JsonDocument.ParseValue(ref reader))
        {
            label.X = doc.RootElement.GetProperty("X").GetInt32();
            label.Y = doc.RootElement.GetProperty("Y").GetInt32();
            label.H = doc.RootElement.GetProperty("H").GetInt32();
            label.W = doc.RootElement.GetProperty("W").GetInt32();
        }
        return label;
    }

    // 序列化逻辑:只写入我们关心的属性
    public override void Write(Utf8JsonWriter writer, CustomLabel value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteNumber("X", value.X);
        writer.WriteNumber("Y", value.Y);
        writer.WriteNumber("H", value.H);
        writer.WriteNumber("W", value.W);
        writer.WriteEndObject();
    }
}

使用的时候把转换器加到序列化配置里:

var options = new JsonSerializerOptions();
options.Converters.Add(new CustomLabelConverter());
var json = JsonSerializer.Serialize(myCustomLabel, options);
方案3:创建DTO(数据传输对象)映射

如果不想依赖序列化框架的特性,或者需要在序列化前做一些属性转换、校验,最稳妥的方式是创建一个和自定义属性对应的DTO类:

// 定义DTO,只包含你要序列化的属性
public class CustomLabelDto
{
    public int X { get; set; }
    public int Y { get; set; }
    public int H { get; set; }
    public int W { get; set; }
}

// 使用时把CustomLabel的属性复制到DTO里
var myCustomLabel = new CustomLabel { X = 10, Y = 20, H = 30, W = 40 };
var dto = new CustomLabelDto
{
    X = myCustomLabel.X,
    Y = myCustomLabel.Y,
    H = myCustomLabel.H,
    W = myCustomLabel.W
};

// 序列化DTO即可
var json = JsonSerializer.Serialize(dto); // 或者用JsonConvert.SerializeObject(dto)

这个方法的好处是解耦了控件类和序列化逻辑,就算以后控件类改了,只要调整DTO的映射就行,非常灵活。


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

火山引擎 最新活动