能否用appsettings.json配置JsonPropertyName映射类模型属性?
需求可行性分析与实现方案
可行性结论
可行,但不能直接在JsonPropertyName特性中注入配置值——因为C#特性的参数必须是编译时常量,无法在运行时动态读取配置内容。需要通过自定义JSON序列化/反序列化逻辑来实现动态映射。
实现方案(基于System.Text.Json)
步骤1:定义配置模型
先把appsettings里的字段配置映射成强类型模型,方便读取:
public class FieldConfig { public string ProjectNameField { get; set; } public string ProjectDescriptionField { get; set; } public string ProjectCreatorField { get; set; } }
步骤2:创建自定义属性名称解析器
通过扩展DefaultJsonTypeInfoResolver来动态替换属性映射,灵活适配配置:
public class DynamicJsonPropertyNameResolver : DefaultJsonTypeInfoResolver { private readonly FieldConfig _fieldConfig; public DynamicJsonPropertyNameResolver(FieldConfig fieldConfig) { _fieldConfig = fieldConfig; } public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) { var typeInfo = base.GetTypeInfo(type, options); if (type == typeof(Project)) { // 遍历Project类属性,替换为配置中的JSON键名 foreach (var property in typeInfo.Properties) { switch (property.Name) { case nameof(Project.ProjectName): property.Name = _fieldConfig.ProjectNameField; break; case nameof(Project.ProjectDescription): property.Name = _fieldConfig.ProjectDescriptionField; break; case nameof(Project.ProjectCreator): property.Name = _fieldConfig.ProjectCreatorField; break; } } } return typeInfo; } }
步骤3:配置序列化选项并注入
在Program.cs(或Startup.cs)中读取配置,注册自定义解析器:
var builder = WebApplication.CreateBuilder(args); // 读取appsettings中的字段配置 var fieldConfig = builder.Configuration.GetSection("fieldConfig").Get<FieldConfig>(); // 配置控制器的JSON序列化选项 builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.TypeInfoResolver = new DynamicJsonPropertyNameResolver(fieldConfig); }); // 若需手动序列化/反序列化,可直接创建配置好的JsonSerializerOptions var jsonOptions = new JsonSerializerOptions { TypeInfoResolver = new DynamicJsonPropertyNameResolver(fieldConfig) }; // 使用示例:反序列化外部API返回的JSON var projectJson = await httpClient.GetStringAsync("external-api/project"); var project = JsonSerializer.Deserialize<Project>(projectJson, jsonOptions);
步骤4:简化Project类
现在可以移除硬编码的JsonPropertyName特性,保持类结构干净:
public class Project { public string ProjectId { get; set; } public string ProjectName { get; set; } public string ProjectDescription { get; set; } public string ProjectCreator { get; set; } }
替代方案(基于Newtonsoft.Json)
如果项目使用Json.NET,可通过自定义IContractResolver实现相同逻辑:
public class DynamicContractResolver : DefaultContractResolver { private readonly FieldConfig _fieldConfig; public DynamicContractResolver(FieldConfig fieldConfig) { _fieldConfig = fieldConfig; } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); if (member.DeclaringType == typeof(Project)) { switch (member.Name) { case nameof(Project.ProjectName): property.PropertyName = _fieldConfig.ProjectNameField; break; case nameof(Project.ProjectDescription): property.PropertyName = _fieldConfig.ProjectDescriptionField; break; case nameof(Project.ProjectCreator): property.PropertyName = _fieldConfig.ProjectCreatorField; break; } } return property; } }
注册配置:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new DynamicContractResolver(fieldConfig); });
内容的提问来源于stack exchange,提问作者Highfield97
相关产品推荐
相关产品推荐

