配置Accept头为application/vnd.api+json遇问题及JSON带反斜杠求助
问题解决方案
问题1:设置Accept头为"application/vnd.api+json"时触发媒体类型不支持错误
可能原因
- 目标API本身不支持
application/vnd.api+json媒体类型,需先确认API文档说明。 - ASP.NET Core项目未配置对该媒体类型的支持,导致框架无法处理对应的响应格式。
- HttpClient的Accept头设置存在冲突,未完全清除原有头信息。
解决方案
- 确认目标API支持:先查阅目标API的官方文档,确认其是否接受
application/vnd.api+json作为Accept头的值。如果API不支持,需改用文档指定的媒体类型。 - 配置ASP.NET Core支持该媒体类型:在
Program.cs中添加对该媒体类型的JSON格式化支持:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; // 添加自定义媒体类型映射 options.OutputFormatters.OfType<SystemTextJsonOutputFormatter>() .First() .SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/vnd.api+json")); });
- 正确设置HttpClient的Accept头:确保清除原有Accept头后再添加新的媒体类型:
_httpClient.DefaultRequestHeaders.Accept.Clear(); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
问题2:返回的JSON结果带有多余反斜杠
原因
当前代码中调用await personCredentials.Content.ReadAsStringAsync()获取的是已经序列化好的JSON字符串,而Ok()方法会将这个字符串再次进行JSON序列化,导致字符串中的双引号被转义,出现多余反斜杠。
解决方案
有两种方式解决:
方式1:反序列化为对象后返回(推荐)
将API响应的JSON字符串反序列化为.NET对象,再返回对象,ASP.NET Core会自动正确序列化:
// 先定义对应的实体类,比如PersonCredential var jsonString = await personCredentials.Content.ReadAsStringAsync(); var credentials = JsonSerializer.Deserialize<List<PersonCredential>>(jsonString); return Ok(credentials);
注:需要根据API返回的JSON结构定义对应的实体类PersonCredential
方式2:直接返回原始JSON内容
使用Content()方法返回原始JSON字符串,并指定媒体类型,避免再次序列化:
var jsonString = await personCredentials.Content.ReadAsStringAsync(); return Content(jsonString, "application/json");
修改后的完整代码示例
[Route("api/[controller]")] [ApiController] [Produces("application/json", "application/vnd.api+json")] // 添加支持的媒体类型 public class ProjectController : ControllerBase // 类名遵循大驼峰命名规范 { private readonly IConfiguration _configuration; private readonly HttpClient _httpClient; public ProjectController(IConfiguration configuration, HttpClient httpClient) { _configuration = configuration; _httpClient = httpClient; } [HttpGet] public async Task<IActionResult> Get() { try { // 设置API密钥 _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _configuration["ApiSettings:ApiKey"]); var content = new StringContent("", Encoding.UTF8, "application/json"); var authResponse = await _httpClient.PostAsync("https://www.example.com/auth", content); if (!authResponse.IsSuccessStatusCode) { return BadRequest("认证失败"); } // 解析认证令牌(注意:如果返回的是JSON对象,建议反序列化为对象提取token,避免直接用字符串) var authToken = await authResponse.Content.ReadAsStringAsync(); // 示例:如果authResponse返回的是{"token":"xxx"},应该反序列化后取token字段 // var authResult = JsonSerializer.Deserialize<AuthResult>(authToken); // var token = authResult.Token; // 设置请求头 _httpClient.DefaultRequestHeaders.Accept.Clear(); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json")); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); var url = "https://www.example.com/api/credential/"; var personCredentials = await _httpClient.GetAsync(url); personCredentials.EnsureSuccessStatusCode(); // 确保请求成功,否则抛出异常 // 方式1:反序列化为对象返回(推荐) var jsonString = await personCredentials.Content.ReadAsStringAsync(); var credentials = JsonSerializer.Deserialize<List<PersonCredential>>(jsonString); return Ok(credentials); // 方式2:直接返回原始JSON // var jsonString = await personCredentials.Content.ReadAsStringAsync(); // return Content(jsonString, "application/json"); } catch (HttpRequestException ex) { string errorMessage = $"API调用错误: {ex.Message}"; return StatusCode((int)ex.StatusCode, errorMessage); } } } // 示例实体类,根据实际API返回结构调整 public class PersonCredential { public int Id { get; set; } public string Name { get; set; } // 其他属性... } // 认证响应实体类(如果需要) public class AuthResult { public string Token { get; set; } }
内容的提问来源于stack exchange,提问作者Anis Khoja
相关产品推荐
相关产品推荐

