ASP.NET Core 6 Web API Swagger与OpenAPI生成器内容类型适配问题
问题根源
ASP.NET Core默认返回的application/json响应会自动附加; charset=utf-8后缀,但你通过OpenAPI生成的客户端仅认可不带后缀的application/json类型,导致返回400状态码时触发类型不匹配错误。直接添加Produces("application/json; charset=utf-8")引发406错误,是因为客户端请求的Accept头通常仅包含application/json,服务器找不到完全匹配的响应类型。
解决方案1:修改Swagger/OpenAPI文档生成规则
通过自定义Swashbuckle过滤器,强制让swagger.json中的响应Content-Type带上charset=utf-8后缀,这样生成的客户端就会以该类型作为预期值。
- 实现自定义
IDocumentFilter:
public class AddCharsetToJsonContentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { foreach (var pathItem in swaggerDoc.Paths.Values) { foreach (var operation in pathItem.Operations.Values) { foreach (var response in operation.Responses.Values) { // 找出所有application/json类型的内容 var jsonEntries = response.Content .Where(kv => kv.Key.Equals("application/json", StringComparison.OrdinalIgnoreCase)) .ToList(); // 删除原有不带charset的条目,添加带charset的条目 foreach (var (key, content) in jsonEntries) { response.Content.Remove(key); response.Content.Add("application/json; charset=utf-8", content); } } } } } }
- 在Program.cs中注册该过滤器:
builder.Services.AddSwaggerGen(c => { // 其他Swagger配置... c.DocumentFilter<AddCharsetToJsonContentFilter>(); });
解决方案2:调整ASP.NET Core的内容协商规则
为避免406错误,让服务器同时接受带/不带charset的Accept头,同时返回带charset的响应:
- 在控制器或Action上同时声明两种Produces类型:
[Produces("application/json", "application/json; charset=utf-8")]
这样服务器会匹配客户端发送的Accept: application/json请求,同时返回application/json; charset=utf-8的响应,既兼容客户端请求,又能让基于修改后swagger.json生成的新客户端匹配响应类型。
解决方案3:配置OpenAPI生成器忽略charset后缀
如果不想修改服务器端代码,也可以在生成客户端时配置OpenAPI生成器,使其忽略Content-Type中的charset部分。以Python客户端为例,生成时添加如下参数:
openapi-generator generate -i swagger.json -g python -o ./client --additional-properties allowCharsetInContentType=true
该参数会让生成的客户端在验证Content-Type时忽略charset后缀,直接匹配主类型application/json。
总结
优先推荐方案1+方案2组合,既能确保swagger.json输出符合预期的Content-Type,又能避免406错误;如果不想修改服务器代码,方案3的生成器配置也能快速解决问题。本质上这个问题是ASP.NET Core的默认响应格式与OpenAPI生成器的严格类型验证之间的不匹配,两种方向的调整都能解决问题。
内容的提问来源于stack exchange,提问作者jsp

