@RequestBody在发出 POST 请求时给出空的 JsonObject

2022-09-04 01:32:20

我有以下方法:

@RequestMapping(value = "/app/write", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public
@ResponseBody
Status writeBuildData(@RequestBody JsonObject templateDataJSON){}

基本上,我发出Ajax请求发送JSON,结果我总是得到一个空的POSTJsonObject {}

JsonObject templateDataJSON = "{}";

但是如果我使用 String 而不是 ,我会得到正确的值。JsonObject

这个程序是用弹簧Mvc 4.1.4制作的。

依赖:

compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
compile 'com.google.code.gson:gson:2.3.1'

任何想法,我错过了什么,为什么没有注射,总是给我?JsonObject{}


答案 1

Spring不再支持Jackson 1作为消息转换器实现。

所以你的

compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'

其实对春天毫无意义。

compile 'com.google.code.gson:gson:2.3.1'

将导致弹簧使用,基本上,做GsonHttpMessageConverter

String json = "{\"random\":\"42\"}";
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(json, JsonObject.class);

JsonObject是 Gson 类型。Gson 意识到了这一点,并且知道如何将 JSON 对象 json 反序列化为它。这将正常工作,并将生成一个值为JsonObject

{"random":"42"}

既然你说你得到了一个空的,我只能假设你的类路径上有Jackson 2。JsonObject

Spring 在如果两者都出现在类路径上之前注册 Jackson。HttpMessageConverterMappingJackson2HttpMessageConverterGsonHttpMessageConverter

对于杰克逊,Spring基本上会把你的请求体反序列化。

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonObject jsonObject = mapper.readValue(json, JsonObject.class);

您将在

{}

这是因为 Jackson 对类型一无所知,因此它必须动态构建反序列化策略。该策略取决于 Jackson 定义为 setter 的属性(对于反序列化的上下文)或任何带有 注释的属性,而这些属性显然没有。因此,它基本上认为该类型没有任何属性(或者可能没有出现在自定义JSON内容中的属性)。因此,由于它忽略了任何未知属性(这会导致它引发异常),因此它只是返回一个新的空对象。JsonObject@JsonPropertyJsonObjectJsonObjectJsonObject

一种解决方案是从类路径中删除 Jackson 2。另一种解决方案是按所需顺序显式添加实例。HttpMessageConverter


答案 2

为什么它失败的解释在Sotirios Delimanolis答案中完美地完成了。

但是,有一个解决方法:

@RequestBody Map<String, String> json

这样,您就可以继续使用 Jackson HttpMessageConverter,并在有效负载中使用自定义对象。