Kestrel MVC Server中返回指定JSON字符串的正确方法及异常原因
问题描述
现有如下C#类定义:
class Fake { public int test { get; set; } }
对应的GET接口实现如下时,返回结果符合预期:
[HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fake = new Fake { test = 1 }; return Ok(fake); }
预期返回JSON:
{ "test": 1 }
现在希望不借助Fake类,直接返回对应JSON字符串,但多次尝试均失败:
- 直接返回JSON字符串
实现代码:
[HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fake = "{ \"test\": 1 }"; return Ok(fake); }
返回结果(带引号的字符串):
"{ \"test\": 1 }"
- 使用
JsonConvert.DeserializeObject
实现代码:
[HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fake = "{ \"test\": 1 }"; return Ok(JsonConvert.DeserializeObject(fake)); }
返回异常结果:
{"test":[]}
- 使用
JsonResult
实现代码:
[HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fake = "{ \"test\": 1 }"; return new JsonResult(fake); }
返回转义后的字符串:
"{ \u0022test\u0022: 1 }"
现需解决两个问题:
- 如何实现直接返回符合预期的JSON格式?
- 第二种尝试出现异常结果的原因是什么?
解决方案与原因分析
一、正确返回预期JSON格式的方法
可以通过以下几种方式实现:
方法1:返回ContentResult并指定媒体类型
直接将JSON字符串作为内容返回,同时设置正确的Content-Type为application/json,避免ASP.NET Core对字符串进行二次序列化:
[HttpGet] public async Task<IActionResult> Get() { var fakeJson = "{ \"test\": 1 }"; return Content(fakeJson, MediaTypeNames.Application.Json); }
方法2:反序列化为JObject或dynamic
使用Newtonsoft.Json将JSON字符串解析为JObject(或dynamic),再通过Ok()返回,框架会将其序列化为正确的JSON对象:
using Newtonsoft.Json.Linq; [HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fakeJson = "{ \"test\": 1 }"; var jsonObj = JObject.Parse(fakeJson); return Ok(jsonObj); }
或者使用dynamic类型:
[HttpGet] [Produces(MediaTypeNames.Application.Json)] public async Task<IActionResult> Get() { var fakeJson = "{ \"test\": 1 }"; dynamic jsonObj = JsonConvert.DeserializeObject(fakeJson); return Ok(jsonObj); }
方法3:使用RawResult(ASP.NET Core 8+)
如果使用ASP.NET Core 8及以上版本,可直接用RawResult返回原始JSON内容:
[HttpGet] public async Task<IActionResult> Get() { var fakeJson = "{ \"test\": 1 }"; return new RawResult(fakeJson) { ContentType = MediaTypeNames.Application.Json }; }
二、第二种尝试返回异常结果的原因
你调用的是无泛型参数的JsonConvert.DeserializeObject(string)方法,该方法默认将JSON反序列化为object类型。当Newtonsoft.Json解析数值1时,若存在类型推断歧义,会错误地将其识别为JArray(空数组),最终框架序列化这个JArray时就输出了"test":[]。
正确的做法是指定反序列化的目标类型,或者使用JObject.Parse确保解析为正确的JSON对象结构,不要依赖无泛型参数的反序列化方法。
内容的提问来源于stack exchange,提问作者Rachel Ambler
相关产品推荐
相关产品推荐

