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

如何动态设置JsonProperty属性名为泛型类型名称实现JSON反序列化?

动态设置泛型类JsonProperty的PropertyName为T的类型名称

原代码中直接在[JsonProperty]属性里使用typeof(T).Name会编译失败,因为Attribute的参数必须是编译时常量,而typeof(T).Name是运行时才能确定的值。下面提供两种可行的实现方案:

方案一:自定义ContractResolver(推荐)

通过自定义Json.NET的契约解析器,在运行时动态修改属性的JSON键名,对业务代码侵入极小。

1. 实现自定义契约解析器

public class AppSettingsContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        // 判断当前属性是否属于AppSettings<T>泛型类的dynproperty属性
        var declaringType = member.DeclaringType;
        if (declaringType.IsGenericType && declaringType.GetGenericTypeDefinition() == typeof(AppSettings<>))
        {
            if (member.Name == nameof(AppSettings<object>.dynproperty))
            {
                // 获取泛型参数T的类型名称,设置为JSON键名
                var genericArg = declaringType.GetGenericArguments()[0];
                property.PropertyName = genericArg.Name;
            }
        }

        return property;
    }
}

2. 简化AppSettings类

移除原来的[JsonProperty]属性,保持类的简洁:

class AppSettings<T>
{
    public T dynproperty { get; set; }
}

3. 反序列化时使用自定义解析器

var serializerSettings = new JsonSerializerSettings
{
    ContractResolver = new AppSettingsContractResolver()
};

var appsettings = JsonConvert.DeserializeObject<AppSettings<PersonModel>>(configData, serializerSettings);

方案二:利用JsonExtensionData手动映射

通过[JsonExtensionData]捕获所有未匹配的JSON属性,在属性的get/set方法中手动完成类型名称与属性的映射。

class AppSettings<T>
{
    [JsonExtensionData]
    private IDictionary<string, JToken> _extensionData;

    public T dynproperty
    {
        get
        {
            var key = typeof(T).Name;
            if (_extensionData.TryGetValue(key, out var token))
            {
                return token.ToObject<T>();
            }
            return default;
        }
        set
        {
            var key = typeof(T).Name;
            _extensionData[key] = JToken.FromObject(value);
        }
    }
}

使用时无需额外配置,直接调用反序列化方法即可:

var appsettings = JsonConvert.DeserializeObject<AppSettings<PersonModel>>(configData);

方案对比

  • 自定义ContractResolver:符合Json.NET的扩展规范,业务代码无额外逻辑,适合全局复用,推荐在复杂场景或需要统一配置时使用。
  • JsonExtensionData:无需额外编写解析器,逻辑内聚在类中,适合简单场景,缺点是需要手动处理JSON令牌与目标类型的转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:30:00