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

C#继承List<T>的自定义类序列化JSON时丢失自定义属性问题

根本原因

你使用的Newtonsoft.Json序列化框架对继承了集合类型(比如List<T>、IEnumerable<T>)的类有默认处理逻辑:会将其识别为纯集合,仅序列化集合内的元素,忽略类上自定义的额外属性,这就是Reason字段丢失的核心原因。
另外需要提前明确:JSON规范中数组结构本身不支持附加自定义键值对属性,所以要保留Reason字段的话,序列化结果必然要调整为「对象包裹数组」的结构,无法做到既是纯数组又带额外属性。

兼容解决方案

以下方案均可以最大程度保留原有类结构和业务逻辑:

方案1:仅修改序列化调用代码(完全不改动原有类定义,兼容性最高)

如果仅需要序列化输出带Reason,不需要反序列化为FooList类型,直接用匿名类包裹原对象即可,只改动序列化一行代码:

// 原有业务逻辑完全不变
var foo = new Foo { Name = "foo1" };
var foo2 = new Foo { Name = "foo2" };
var foos = new List<Foo> { foo, foo2 };
var fooList = new FooList();
fooList.Reason = "Strange";
fooList.AddRange(foos);
// 仅修改序列化这一行
var jsonFoo = JsonConvert.SerializeObject(new {
    fooList.Reason,
    Items = fooList
});

序列化输出结果为:

{"Reason":"Strange","Items":[{"Name":"foo1"},{"Name":"foo2"}]}

方案2:少量修改FooList定义(适配序列化+反序列化场景,原有业务调用完全无感知)

给FooList加上强制按对象序列化的特性,额外暴露集合元素属性即可,原有所有对FooList的集合操作(Add、遍历、作为List<Foo>传参等)都完全不受影响:

// 加特性强制按普通对象序列化
[Newtonsoft.Json.JsonObject]
public class FooList:List<Foo>
{
    public string  Reason { get; set; }
    // 私有属性不对外暴露,仅用于序列化输出集合元素
    [Newtonsoft.Json.JsonProperty(nameof(Items))]
    private List<Foo> Items => this;
}

修改后原有序列化代码不需要任何改动,输出结果和方案1一致,同时支持反序列化直接转回FooList对象。

方案3:自定义JsonConverter(完全不改动原有类定义,同时支持序列化反序列化)

如果连FooList的定义都不想改,可以自定义序列化转换器,全局或单独指定给FooList使用即可,适合FooList已经在大量场景引用,完全不能改类定义的场景:

public class FooListConverter : JsonConverter<FooList>
{
    public override void WriteJson(JsonWriter writer, FooList value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        writer.WritePropertyName(nameof(FooList.Reason));
        serializer.Serialize(writer, value.Reason);
        writer.WritePropertyName("Items");
        serializer.Serialize(writer, value.ToList());
        writer.WriteEndObject();
    }

    public override FooList ReadJson(JsonReader reader, Type objectType, FooList existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        var reason = jObj[nameof(FooList.Reason)]?.ToString();
        var items = jObj["Items"]?.ToObject<List<Foo>>() ?? new List<Foo>();
        var res = new FooList { Reason = reason };
        res.AddRange(items);
        return res;
    }
}

使用时指定转换器即可:

var jsonFoo = JsonConvert.SerializeObject(fooList, new FooListConverter());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:48:03