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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:06:19