如何动态设置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
相关产品推荐
相关产品推荐

