@RequestBody gives an empty JsonObject when making a POST request

I have the following method:

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

      

Basically I am making an Ajax request POST

sending JSON, I always get empty JsonObject {}

in the result

JsonObject templateDataJSON = "{}";

      

But if I use String instead JsonObject

, I get the correct value.

This application is built with Spring Mvc 4.1.4 .

Dependencies:

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

      

Any idea what I am missing and why JsonObject

not injected and always giving me {}

?

+4


source to share


4 answers


Spring no longer supports Jackson 1 as its message converter implementation.

So your

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

      

doesn't actually make sense for Spring.

Your

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

      

will cause Spring to use GsonHttpMessageConverter

and basically do

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

      

JsonObject

- type Gson. Gson knows this and knows how to deserialize a JSON json object into it. This will work correctly and will generate JsonObject

whose value is



{"random":"42"}

      

Since you say you are getting empty JsonObject

, I can only assume that you have Jackson 2 in your classpath.

Spring registers Jackson HttpMessageConverter

, MappingJackson2HttpMessageConverter

before it GsonHttpMessageConverter

, if present on the classpath.

With Jackson, Spring deserializes the request body basically as such

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

      

which you will see in

{}

      

This is because Jackson doesn't know anything about the type JsonObject

, so he must build a deserialization strategy dynamically. This strategy relies on properties that Jackson defines as setters (for the deserialization context), or something annotated with @JsonProperty

, which obviously JsonObject

doesn't have. So it basically thinks the type JsonObject

doesn't have any properties (or maybe none that appear in your custom JSON content). This way, and because it ignores any unknown properties (which might have caused it to be thrown), it just returns a new empty object JsonObject

.

One solution is to remove Jackson 2 from the classpath. Another solution is to explicitly add the instances HttpMessageConverter

in the order you want.

+7


source


What is JsonObject? You have to use an object that represents the json you are sending. Something like

public class Foo {
    String foo;
    String bar;
}

      

instead of JsonObject



and json like:

{
  "foo" : "val",
  "bar" : "val"
}

      

0


source


0


source


An explanation of why this fails is beautifully done in Sotirios Delimanolis' answer.

However, there is a workaround:

@RequestBody Map<String, String> json

      

This way you can continue to use Jackson's HttpMessageConverter and work with custom objects in the payload.

0


source







All Articles