如何在System.Text.Json中优先序列化基类属性
如何在System.Text.Json中优先序列化基类属性
嘿,我之前也碰到过这个需求!默认情况下System.Text.Json序列化继承类的时候,会把子类的属性排在前面,基类的属性反而靠后。如果想让基类属性优先输出,有两种实用的方法,我给你详细唠唠:
方法一:用JsonPropertyOrder特性手动指定顺序
这是最直接简单的办法,适合属性不多或者项目规模不大的场景。你只需要给基类的属性设置一个更小的JsonPropertyOrder值,子类的属性设置稍大一点的数值,System.Text.Json就会按照Order从小到大的顺序序列化属性。
比如修改你的类结构:
using System.Text.Json.Serialization; public class ParentClass { [JsonPropertyOrder(-2)] public int ParentProperty1 { get; set; } [JsonPropertyOrder(-2)] public int ParentProperty2 { get; set; } } public class ChildClass: ParentClass { [JsonPropertyOrder(-1)] public int ChildProperty1 { get; set; } [JsonPropertyOrder(-1)] public int ChildProperty2 { get; set; } } public class GrandchildClass: ChildClass { [JsonPropertyOrder(0)] public int GrandchildProperty1 { get; set; } [JsonPropertyOrder(0)] public int GrandchildProperty2 { get; set; } }
这里我给基类属性设为-2,子类-1,孙子类0——数值越小,序列化时越靠前。这样序列化出来的JSON里,Parent的属性就会排在最前面,接着是Child,最后是Grandchild的属性。
方法二:自定义JsonConverter全局控制顺序
如果你的继承类很多,每个属性都加特性太繁琐,那可以写一个自定义的JSON转换器,手动控制序列化时先处理基类属性,再处理子类的。
比如这个通用的转换器:
using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; public class BaseFirstConverter<T> : JsonConverter<T> { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 反序列化用默认逻辑就够,我们主要改序列化的顺序 return JsonSerializer.Deserialize<T>(ref reader, options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { writer.WriteStartObject(); // 先收集从基类到子类的类型链(排除object) var typeChain = new List<Type>(); var currentType = typeof(T); while (currentType != null && currentType != typeof(object)) { typeChain.Insert(0, currentType); currentType = currentType.BaseType; } // 遍历类型链,先序列化基类的属性 foreach (var type in typeChain) { // 只取当前类型自己声明的公共属性,避免重复序列化继承来的属性 var properties = type.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (var prop in properties) { // 处理JsonPropertyName特性,确保别名生效 var propName = prop.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name ?? prop.Name; var propValue = prop.GetValue(value); // 用默认序列化逻辑写入属性 JsonSerializer.Serialize( writer, propName: propName, value: propValue, inputType: prop.PropertyType, options: options); } } writer.WriteEndObject(); } }
使用的时候,只需要在JsonSerializerOptions里添加这个转换器就行:
var grandchild = new GrandchildClass { ParentProperty1 = 1, ParentProperty2 = 2, ChildProperty1 = 3, ChildProperty2 = 4, GrandchildProperty1 = 5, GrandchildProperty2 = 6 }; var options = new JsonSerializerOptions(); options.Converters.Add(new BaseFirstConverter<GrandchildClass>()); var json = JsonSerializer.Serialize(grandchild, options);
这个转换器会自动先处理最上层的基类属性,再依次处理子类的,完全不用给每个属性加特性,适合大型项目或者有很多继承类的场景。
小提醒
如果你的属性还加了其他System.Text.Json的特性(比如JsonIgnore),自定义转换器里的默认序列化逻辑会自动识别,不用额外处理,这点很省心。
内容来源于stack exchange
相关产品推荐
相关产品推荐

