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

Myt*_*hul 4 java spring json jackson

我有以下方法:

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

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

JsonObject templateDataJSON = "{}";
Run Code Online (Sandbox Code Playgroud)

但如果我使用String代替JsonObject,我得到正确的值.

这个应用程序是由Spring Mvc 4.1.4制作的.

依赖关系:

compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
compile 'com.google.code.gson:gson:2.3.1'
Run Code Online (Sandbox Code Playgroud)

知道我错过了什么,为什么JsonObject没有注射,总是给我{}

Sot*_*lis 8

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

所以你的

compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
Run Code Online (Sandbox Code Playgroud)

对Spring来说实际上毫无意义.

您的

compile 'com.google.code.gson:gson:2.3.1'
Run Code Online (Sandbox Code Playgroud)

将导致Spring使用GsonHttpMessageConverter,基本上,做

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

JsonObject是Gson类型.Gson知道它并且知道如何将JSON对象json反序列化到它中.这将正常工作,并将生成JsonObject具有值的值

{"random":"42"}
Run Code Online (Sandbox Code Playgroud)

既然你说你得到的是空的JsonObject,我只能假设你的类路上有杰克逊2.

春季注册杰克逊HttpMessageConverter,MappingJackson2HttpMessageConverter之前,GsonHttpMessageConverter如果两者都存在的类路径上.

对于杰克逊,Spring会基本上对您的请求主体进行反序列化

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonObject jsonObject = mapper.readValue(json, JsonObject.class);
Run Code Online (Sandbox Code Playgroud)

你会注意到的结果

{}
Run Code Online (Sandbox Code Playgroud)

这是因为杰克逊对类型一无所知,JsonObject所以它必须动态地建立反序列化策略.该策略取决于杰克逊定义为安装者(用于反序列化的背景)或任何注释的属性@JsonProperty,这显然JsonObject是没有的.所以它基本上认为该类型JsonObject没有任何属性(或者可能没有出现在您的自定义JSON内容中).因此,并且因为它忽略了任何未知的属性(这会导致它抛出异常),它只返回一个新的空JsonObject对象.

一种解决方案是从类路径中删除Jackson 2.另一种解决方案是以HttpMessageConverter您想要的顺序显式添加实例.


Raf*_*ael 5

Sotirios Delimanolis answer 完美地解释了它失败的原因。

但是有一个解决方法:

@RequestBody Map<String, String> json
Run Code Online (Sandbox Code Playgroud)

这样您就可以继续使用 Jackson HttpMessageConverter 并处理负载中的自定义对象。