如何在ASP.NET Core 7中将纯字符串以JSON格式返回?
ASP.NET Core 7全局设置字符串响应默认返回application/json
问题背景
从.NET Framework迁移到ASP.NET Core 7时,遇到响应序列化差异:返回简单字符串的端点默认Content-Type为text/plain,字符串不带引号,不符合原ASP.NET Framework中默认返回JSON格式(带引号、Content-Type为application/json)的行为。
示例控制器代码:
[ApiController] [Route("[controller]")] public class SanityController : ControllerBase { public SanityController() { } [HttpGet] public string Get() { return "Where are the quotes?"; } }
Program.cs配置(已尝试的JSON序列化配置):
var builder = WebApplication.CreateBuilder(args); // 曾尝试配置JsonOptions,效果和AddJsonOptions一致 //builder.Services.Configure<JsonOptions>(options => //{ // options.SerializerOptions.IncludeFields = true; // options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); // options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; // options.SerializerOptions.PropertyNameCaseInsensitive = true; //}); builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.IncludeFields = true; options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; }); app.Run();
目前问题:
- 返回字符串的端点默认Content-Type为
text/plain - 修改客户端Accept头为
application/json时可返回JSON,但浏览器直接访问仍返回text/plain - 单个方法添加
[Produces("application/json")]可解决,但需要全局生效的方案
解决方案
方法1:自定义字符串输出格式化器
创建自定义输出格式化器,覆盖字符串类型的序列化逻辑,强制返回带引号的JSON格式:
- 实现自定义格式化器类:
public class StringJsonOutputFormatter : TextOutputFormatter { public StringJsonOutputFormatter() { SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json")); SupportedEncodings.Add(Encoding.UTF8); SupportedEncodings.Add(Encoding.Unicode); } protected override bool CanWriteType(Type? type) { return type == typeof(string); } public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { var response = context.HttpContext.Response; var value = context.Object as string; var json = JsonSerializer.Serialize(value); await response.WriteAsync(json, selectedEncoding); } }
- 在Program.cs中注册该格式化器(插入到格式化器列表最前面,确保优先生效):
builder.Services.AddControllers(options => { options.OutputFormatters.Insert(0, new StringJsonOutputFormatter()); }) .AddJsonOptions(options => { options.JsonSerializerOptions.IncludeFields = true; options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });
方法2:全局添加Produces特性
通过全局过滤器强制所有控制器默认返回application/json类型:
builder.Services.AddControllers(options => { options.Filters.Add(new ProducesAttribute("application/json")); }) .AddJsonOptions(options => { options.JsonSerializerOptions.IncludeFields = true; options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });
方法3:使用ActionFilter拦截转换字符串响应
创建ActionFilter,拦截返回字符串的结果并转换为JSON格式:
- 实现ActionFilter类:
public class StringToJsonFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { if (context.Result is ObjectResult objectResult && objectResult.Value is string strValue) { var jsonValue = JsonSerializer.Serialize(strValue); context.Result = new ContentResult { Content = jsonValue, ContentType = "application/json", StatusCode = objectResult.StatusCode }; } } }
- 全局注册该Filter:
builder.Services.AddControllers(options => { options.Filters.Add<StringToJsonFilter>(); }) .AddJsonOptions(options => { options.JsonSerializerOptions.IncludeFields = true; options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });
说明
- 方法1是最贴合原ASP.NET Framework行为的方案,直接修改字符串类型的序列化规则
- 方法2强制全局响应类型为application/json,浏览器访问时也会返回带引号的JSON字符串
- 方法3适合需要对字符串响应做额外处理的场景
内容的提问来源于stack exchange,提问作者JWrightII
相关产品推荐
相关产品推荐

