ASP.NET Core中基于控制器条件序列化重命名属性的实现
基于System.Text.Json实现ASP.NET Core控制器特定属性重命名
解决方案思路
通过自定义JsonConverterFactory实现针对特定模型类的属性名称映射,再将该转换器注入到自定义的ExternalJsonOutputFormatter中,最后配置目标控制器使用此格式化器,默认控制器保留原有序列化规则。
步骤1:定义模型类
public class ClassA { public string OriginalPropA1 { get; set; } public int OriginalPropA2 { get; set; } public string NormalProp { get; set; } } public class ClassB { public string OriginalPropB1 { get; set; } public bool NormalPropB { get; set; } }
步骤2:实现自定义属性重命名转换器
创建JsonConverterFactory子类,针对ClassA和ClassB配置属性名映射,在序列化时替换属性名称:
public class CustomPropertyRenameConverter : JsonConverterFactory { // 配置模型类的属性名映射关系 private readonly Dictionary<Type, Dictionary<string, string>> _propertyMappings = new() { { typeof(ClassA), new Dictionary<string, string> { { nameof(ClassA.OriginalPropA1), "RenamedA1" }, { nameof(ClassA.OriginalPropA2), "RenamedA2" } } }, { typeof(ClassB), new Dictionary<string, string> { { nameof(ClassB.OriginalPropB1), "RenamedB1" } } } }; public override bool CanConvert(Type typeToConvert) { return _propertyMappings.ContainsKey(typeToConvert); } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var converterType = typeof(CustomRenameConverter<>).MakeGenericType(typeToConvert); return (JsonConverter)Activator.CreateInstance(converterType, _propertyMappings[typeToConvert]); } // 泛型转换器实现具体序列化逻辑 private class CustomRenameConverter<T> : JsonConverter<T> { private readonly Dictionary<string, string> _propertyMap; private readonly JsonConverter<T> _defaultConverter; public CustomRenameConverter(Dictionary<string, string> propertyMap) { _propertyMap = propertyMap; _defaultConverter = (JsonConverter<T>)JsonSerializerOptions.Default.GetConverter(typeof(T)); } // 无需自定义反序列化,直接使用默认实现 public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return _defaultConverter.Read(ref reader, typeToConvert, options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // 先序列化为JsonDocument,再遍历替换属性名 using var jsonDoc = JsonDocument.Parse(JsonSerializer.Serialize(value, options)); writer.WriteStartObject(); foreach (var property in jsonDoc.RootElement.EnumerateObject()) { var propertyName = _propertyMap.TryGetValue(property.Name, out var newName) ? newName : property.Name; writer.WritePropertyName(propertyName); property.Value.WriteTo(writer); } writer.WriteEndObject(); } } }
步骤3:修改自定义输出格式化器
在ExternalJsonOutputFormatter中注入自定义转换器,确保序列化时应用属性重命名规则:
public class ExternalJsonOutputFormatter : SystemTextJsonOutputFormatter { public ExternalJsonOutputFormatter(JsonSerializerOptions options) : base(CreateCustomOptions(options)) { } private static JsonSerializerOptions CreateCustomOptions(JsonSerializerOptions baseOptions) { var customOptions = new JsonSerializerOptions(baseOptions); // 添加属性重命名转换器 customOptions.Converters.Add(new CustomPropertyRenameConverter()); return customOptions; } }
步骤4:注册格式化器并配置控制器
在Program.cs中注册自定义格式化器,并确保XController使用该格式化器:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(options => { // 获取默认Json配置作为基础 var baseJsonOptions = new JsonSerializerOptions(SystemTextJsonSerializerProvider.DefaultSerializerOptions); // 将自定义格式化器插入到输出格式化器列表首位 options.OutputFormatters.Insert(0, new ExternalJsonOutputFormatter(baseJsonOptions)); }) // 配置默认Json序列化规则(供YController使用) .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; }); var app = builder.Build(); app.UseRouting(); app.MapControllers(); app.Run();
步骤5:编写控制器代码
XController返回模型时会自动应用属性重命名,YController使用默认规则:
[ApiController] [Route("api/x")] public class XController : ControllerBase { [HttpGet("classa")] public IActionResult GetClassA() { return Ok(new ClassA { OriginalPropA1 = "TestA1", OriginalPropA2 = 123, NormalProp = "Normal" }); // 输出:{"RenamedA1":"TestA1","RenamedA2":123,"NormalProp":"Normal"} } [HttpGet("classb")] public IActionResult GetClassB() { return Ok(new ClassB { OriginalPropB1 = "TestB1", NormalPropB = true }); // 输出:{"RenamedB1":"TestB1","NormalPropB":true} } } [ApiController] [Route("api/y")] public class YController : ControllerBase { [HttpGet("classa")] public IActionResult GetClassA() { return Ok(new ClassA { OriginalPropA1 = "TestA1", OriginalPropA2 = 123, NormalProp = "Normal" }); // 输出(默认驼峰):{"originalPropA1":"TestA1","originalPropA2":123,"normalProp":"Normal"} } }
内容的提问来源于stack exchange,提问作者markvgti
相关产品推荐
相关产品推荐

