为什么在JavaSpring中获取JSON时会出现406错误?

为什么在JavaSpring中获取JSON时会出现406错误?,java,json,spring,controller,response,Java,Json,Spring,Controller,Response,当我通常使用JavaSpring创建返回JSON数据的控制器端点时,我的返回类型通常是String;我将toString()我的JSON对象并在Javascript中解析它们。最近,我在某个地方读到这样做不是“正确”的方式(试图遵循最佳实践和指导方针)。我正在启动一个新项目,其中我的返回类型是一个JSON对象(依赖项是org.JSON) 当我尝试在浏览器中点击端点时,我得到一个406错误,描述为“此请求标识的资源只能根据请求“接受”标题生成具有不可接受特征的响应。” 下面是我的端点现在的样子:

当我通常使用JavaSpring创建返回JSON数据的控制器端点时,我的返回类型通常是
String
;我将
toString()
我的JSON对象并在Javascript中解析它们。最近,我在某个地方读到这样做不是“正确”的方式(试图遵循最佳实践和指导方针)。我正在启动一个新项目,其中我的返回类型是一个JSON对象(依赖项是
org.JSON

当我尝试在浏览器中点击端点时,我得到一个406错误,描述为“此请求标识的资源只能根据请求“接受”标题生成具有不可接受特征的响应。”

下面是我的端点现在的样子:

@RequestMapping(value = "/api/get-items", method = {RequestMethod.GET, RequestMethod.POST}, headers = "Accept=application/json")
@ResponseBody
public JSONObject doGetItems(HttpServletRequest request, HttpServletResponse response) {
    JSONObject data = new JSONObject();
    JSONArray items = new JSONArray();
    JSONObject item1 = new JSONObject().put("id", 123);
    JSONObject item2 = new JSONObject().put("id", 456);
    JSONObject item3 = new JSONObject().put("id", 789);
    items.put(item1).put(item2).put(item3);
    data.put("data", items);
    return data;
}
我如何才能让它工作并返回JSON?或者我应该返回JSON对象的字符串化版本,而我一直都在正确地执行此操作

更新

首先,我尝试在
@RequestMapping
注释中取出
headers
参数。我仍然有一个406错误

然后,我尝试在
@RequestMapping
注释中更改/添加参数,但也没有成功。这就是我尝试将其更改为:

@RequestMapping(value = "/api/get-items",
                method = {RequestMethod.GET, RequestMethod.POST},
                headers = "Accept=*/*",
                produces = MediaType.APPLICATION_JSON_VALUE)

我仍然收到一个406错误。

超文本传输协议(HTTP)406不可接受客户端错误响应代码表示服务器无法生成与请求的主动内容协商头中定义的可接受值列表相匹配的响应,服务器不愿意提供默认表示

主动式内容协商标题包括:

客户端(例如,您的Web浏览器或我们的CheckUpDown robot)可以向Web服务器(运行Web站点)指示它将从Web服务器接收回的数据的特征。这是使用以下类型的“接受标头”完成的:

接受:客户端接受的MIME类型。例如,浏览器可能只接受它知道如何处理的返回类型的数据(HTML文件、GIF文件等)

接受字符集:客户端接受的字符集

接受编码:客户机接受的数据编码,例如它能理解的文件格式

接受语言:客户接受的自然语言(英语、德语等)

接受范围:客户端是否从资源(即资源的一部分)接受字节范围


通过更改或删除客户端的标题内容,它应该可以正常工作。

当您指定
headers=“Accept=application/json”
时,您的意思是
Accept
标题必须存在并具有该值

客户端没有准确地发送该值,也没有理由要求它这样做,因为
Accept
头值是一个逗号分隔的可接受值列表,所以它只需要列出
application/json
,它不必只指定该值

要修复此问题,请将
headers=“Accept=application/json”
替换为
products=“application/json”


当然,客户端仍然需要指定
application/json
application/*
*/*
是可以接受的。

Un没有正确理解。Spring不处理org.json.JSONObject的实例。它使用Jackson(或GSON,取决于类路径中的内容)自动从实际的Java类解析/封送到实际的Java类。因此,如果您想返回一个项目数组,其中每个项目都有一个ID、一个名称和一个startInstant,那么只需返回一个列表即可。有关官方示例,请参阅。@JBNizet我尝试使用gson将我的一个端点中的所有
JSONObject
s和
JSONArray
s更改为
JSONObject
JSONArray
,但随后出现500个错误,错误是“无法编写JSON:这不是JSON原语”。再次阅读我的评论。您不应该返回JSONArray或JSONObject。您应该返回POJO,它将被映射到JSON。如示例所示,我喜欢使用.Easy。我确实读过你的评论。它的一部分是“或GSON”,所以我尝试了
JsonObject
JsonArray
。无论如何,我现在理解了如何使用Java对象。如果我
toString()
使用
org.JSON
构建的JSON对象,Spring实际上会处理其余的对象,并将它们作为实际的JSON返回。我同意这一点;只是我的一个误会。如果你把你的回复作为答案提交,我会把它标记为正确的。更新了原始帖子。我尝试删除
@RequestMapping
注释中的
headers
参数,但没有成功。我更新了我原来的帖子。我添加了
products=“application/json”
,还添加了
headers=Accept=*/*
,但效果并不理想。@aCarella Remove
headers=
。我的回答中的替换就是这个意思。我试过了,但也没用。我知道问题出在哪里了。在Spring中使用@ResponseBody时,不必构造实际的JSON对象和数组。Java数据结构可以与控制器方法一起使用和返回,它们将被自动转换。在我的例子中,如果您使用org.JSON构造JSON对象和数组,您必须将它们转换为字符串,因为Spring不会处理它们。这有点像双重工作,因为Spring已经使用Jackson来JSONify对象了。@aCarella所以第一个完全正确,是吗?