告别复杂配置:ASP.NET Core格式化器让数据序列化更简单
在Web开发中,数据序列化(Serialization)是前后端通信的核心环节。当你使用ASP.NET Core构建API时,是否曾为JSON/XML格式转换、日期格式统一、特殊类型处理而头疼?本文将带你深入了解ASP.NET Core格式化器(Formatter)机制,通过简单配置即可实现高效、灵活的数据转换,让你彻底摆脱手动序列化的繁琐工作。
什么是格式化器?
ASP.NET Core格式化器是处理HTTP请求/响应数据转换的组件,主要负责:
- 将客户端发送的JSON/XML等格式数据反序列化为.NET对象(输入格式化器)
- 将.NET对象序列化为客户端可理解的格式(输出格式化器)
框架默认提供了多种格式化器,位于src/Mvc/Mvc.Formatters.Xml/src/目录下,包括:
- XmlSerializerInputFormatter:XML输入格式化器,代码见XmlSerializerInputFormatter.cs
- XmlSerializerOutputFormatter:XML输出格式化器,代码见XmlSerializerOutputFormatter.cs
- JsonSerializer:系统内置的JSON序列化器,支持多种配置选项
格式化器工作原理
ASP.NET Core请求处理管道中,格式化器的工作流程如下:
输入格式化器核心代码逻辑:
public override async Task<InputFormatterResult> ReadRequestBodyAsync(
InputFormatterContext context, Encoding encoding)
{
// 1. 创建XML读取器
using var xmlReader = CreateXmlReader(readStream, encoding, type);
// 2. 获取缓存的序列化器
var serializer = GetCachedSerializer(type);
// 3. 反序列化XML为对象
var deserializedObject = serializer.Deserialize(xmlReader);
return InputFormatterResult.Success(deserializedObject);
}
快速上手:默认JSON格式化器
ASP.NET Core默认启用JSON格式化器,只需在Program.cs中添加控制器支持即可:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // 自动注册JSON格式化器
var app = builder.Build();
app.MapControllers();
app.Run();
此时你的API已支持JSON格式的请求和响应。例如以下控制器:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public ActionResult<List<Product>> GetProducts()
{
return new List<Product>
{
new Product { Id = 1, Name = "笔记本电脑", Price = 5999.99m },
new Product { Id = 2, Name = "智能手机", Price = 3999.99m }
};
}
}
会自动返回JSON格式响应:
[
{"id":1,"name":"笔记本电脑","price":5999.99},
{"id":2,"name":"智能手机","price":3999.99}
]
高级配置:自定义JSON序列化选项
通过AddJsonOptions可以全局配置JSON序列化行为,常见场景包括:
1. 日期格式统一
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// 设置全局日期格式
options.JsonSerializerOptions.Converters.Add(
new DateTimeConverterWithFormat("yyyy-MM-dd HH:mm:ss"));
});
2. 驼峰命名转换
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// 属性名称采用驼峰命名(如ProductName -> productName)
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
3. 忽略空值属性
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// 序列化时忽略空值属性
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});
XML格式化器使用指南
虽然JSON是当前主流,但在企业系统中XML仍广泛使用。启用XML格式化器只需添加对应服务:
builder.Services.AddControllers()
.AddXmlSerializerFormatters(); // 添加XML格式化器
添加后,API将同时支持JSON和XML格式,客户端通过Accept请求头指定所需格式:
Accept: application/json(默认)Accept: application/xml
XML序列化器配置示例:
builder.Services.AddControllers()
.AddXmlOptions(options =>
{
// 配置XML写入器设置
options.XmlSerializerWriterSettings.Indent = true;
options.XmlSerializerWriterSettings.OmitXmlDeclaration = false;
});
XML输出示例:
<ArrayOfProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Product>
<Id>1</Id>
<Name>笔记本电脑</Name>
<Price>5999.99</Price>
</Product>
<Product>
<Id>2</Id>
<Name>智能手机</Name>
<Price>3999.99</Price>
</Product>
</ArrayOfProduct>
处理复杂场景:自定义格式化器
当系统需要支持特殊格式(如CSV、Protocol Buffers)时,可以创建自定义格式化器。以下是实现CSV输出格式化器的关键步骤:
- 创建格式化器类继承
TextOutputFormatter - 重写
CanWriteType方法指定支持的类型 - 实现
WriteResponseBodyAsync方法完成序列化
public class CsvOutputFormatter : TextOutputFormatter
{
public CsvOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
SupportedEncodings.Add(Encoding.UTF8);
}
protected override bool CanWriteType(Type? type)
{
// 支持IEnumerable类型
return type != null && typeof(IEnumerable).IsAssignableFrom(type);
}
public override async Task WriteResponseBodyAsync(
OutputFormatterWriteContext context, Encoding selectedEncoding)
{
// CSV序列化逻辑实现
var response = context.HttpContext.Response;
using var writer = new StreamWriter(response.Body, selectedEncoding);
// ... 写入CSV内容
await writer.FlushAsync();
}
}
注册自定义格式化器:
builder.Services.AddControllers(options =>
{
options.OutputFormatters.Add(new CsvOutputFormatter());
});
性能优化:序列化器缓存机制
ASP.NET Core格式化器内置缓存机制,避免重复创建序列化器实例。以XML序列化器为例,代码位于XmlSerializerOutputFormatter.cs:
// 使用ConcurrentDictionary缓存序列化器
private readonly ConcurrentDictionary<Type, object> _serializerCache = new ConcurrentDictionary<Type, object>();
protected virtual XmlSerializer GetCachedSerializer(Type type)
{
if (!_serializerCache.TryGetValue(type, out var serializer))
{
serializer = CreateSerializer(type);
if (serializer != null)
{
_serializerCache.TryAdd(type, serializer);
}
}
return (XmlSerializer)serializer!;
}
此机制显著提升高频序列化场景的性能,尤其对大型对象和复杂类型效果明显。
常见问题解决方案
1. 日期时间格式问题
默认JSON序列化器使用ISO 8601格式(如"2023-10-01T12:30:45"),如需自定义格式:
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(
new DateTimeConverterWithFormat("yyyy-MM-dd HH:mm:ss"));
});
2. 循环引用问题
当对象存在循环引用时,添加以下配置:
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
3. 枚举类型序列化
默认枚举序列化为整数,如需序列化为字符串:
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
总结与最佳实践
ASP.NET Core格式化器为数据序列化提供了强大支持,建议遵循以下最佳实践:
- 优先使用内置格式化器:JSON和XML格式化器已覆盖大多数场景,位于src/Mvc/Mvc.Formatters.Xml/src/
- 全局配置优于局部配置:通过
AddJsonOptions和AddXmlOptions统一配置 - 注意性能优化:利用内置缓存机制,避免频繁创建序列化器
- 实现自定义格式化器:对特殊格式需求,继承
TextOutputFormatter/TextInputFormatter
通过合理使用格式化器,你可以将更多精力放在业务逻辑实现上,而非数据格式转换。ASP.NET Core格式化器机制的灵活性和扩展性,将为你的API开发带来极大便利。
希望本文能帮助你更好地理解和使用ASP.NET Core格式化器。如果觉得有用,请点赞收藏,关注获取更多ASP.NET Core实用技巧!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



