System.Text.Json序列化自定义Attribute类时抛出异常求助
问题说明
我创建了一个用于标记扩展的自定义Attribute类ConfigNameAttribute,之前用Newtonsoft.Json序列化完全正常,但切换到System.Text.Json时,序列化这个继承自Attribute的类会抛出异常:
System.InvalidOperationException: 'Method may only be called on a Type for which Type.IsGenericParameter is true.'
只要移除Attribute继承,序列化就恢复正常。相关代码如下:
自定义Attribute类:
public class ConfigNameAttribute : Attribute { public ConfigNameAttribute(string name, bool enable) { this.name = name; this.enable = enable; } public string name { get; set; } public bool enable { get; set; } }
序列化代码:
var text = JsonSerializer.Serialize(temp);
问题原因
System.Text.Json在序列化Attribute派生类时,会默认尝试序列化Attribute基类的内部属性(比如TypeId),而这些属性的实现逻辑和普通类型不同,访问时触发了上述异常。Newtonsoft.Json则默认不会序列化Attribute的基类成员,所以没有这个问题。
解决方案
方案一:自定义JsonConverter指定序列化字段
创建一个针对ConfigNameAttribute的转换器,手动控制要序列化的属性,避开Attribute基类的问题:
public class ConfigNameAttributeConverter : JsonConverter<ConfigNameAttribute> { public override ConfigNameAttribute Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; string name = root.GetProperty("name").GetString(); bool enable = root.GetProperty("enable").GetBoolean(); return new ConfigNameAttribute(name, enable); } public override void Write(Utf8JsonWriter writer, ConfigNameAttribute value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteString("name", value.name); writer.WriteBoolean("enable", value.enable); writer.WriteEndObject(); } }
使用时在序列化选项中添加转换器:
var options = new JsonSerializerOptions(); options.Converters.Add(new ConfigNameAttributeConverter()); var text = JsonSerializer.Serialize(temp, options);
方案二:拆分类型(保留Attribute特性)
如果这个类既要作为Attribute使用,又要被序列化,拆分出一个数据类分离职责:
// 用于序列化的数据类 public class ConfigNameData { public string name { get; set; } public bool enable { get; set; } } // 保留Attribute特性的类 public class ConfigNameAttribute : Attribute { public ConfigNameAttribute(string name, bool enable) { Data = new ConfigNameData { name = name, enable = enable }; } public ConfigNameData Data { get; set; } }
序列化时只处理数据类部分:
var text = JsonSerializer.Serialize(temp.Data);
方案三:移除Attribute继承(无需特性功能时)
如果这个类不需要承担Attribute的标记功能,直接去掉继承即可:
public class ConfigNameAttribute // 移除: Attribute { public ConfigNameAttribute(string name, bool enable) { this.name = name; this.enable = enable; } public string name { get; set; } public bool enable { get; set; } }
内容的提问来源于stack exchange,提问作者Magals
相关产品推荐
相关产品推荐

