26

I wanted to write a small and simple REST service using Spring Boot. Here is the REST service code:

@Async
@RequestMapping(value = "/getuser", method = POST, consumes = "application/json", produces = "application/json")
public @ResponseBody Record getRecord(@RequestBody Integer userId) {
    Record result = null;
    // Omitted logic

    return result;
}

The JSON object I sent is the following:

{
    "userId": 3
}

And here is the exception I got:

WARN 964 --- [ XNIO-2 task-7] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of java.lang.Integer out of START_OBJECT token at [Source: java.io.PushbackInputStream@12e7333c; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.Integer out of START_OBJECT token at [Source: java.io.PushbackInputStream@12e7333c; line: 1, column: 1]

3 Answers 3

24

Obviously Jackson can not deserialize the passed JSON into an Integer. If you insist to send a JSON representation of a User through the request body, you should encapsulate the userId in another bean like the following:

public class User {
    private Integer userId;
    // getters and setters
}

Then use that bean as your handler method argument:

@RequestMapping(...)
public @ResponseBody Record getRecord(@RequestBody User user) { ... }

If you don't like the overhead of creating another bean, you could pass the userId as part of Path Variable, e.g. /getuser/15. In order to do that:

@RequestMapping(value = "/getuser/{userId}", method = POST, produces = "application/json")
public @ResponseBody Record getRecord(@PathVariable Integer userId) { ... }

Since you no longer send a JSON in the request body, you should remove that consumes attribute.

Sign up to request clarification or add additional context in comments.

4 Comments

I know the problem is with the Jackson Object Mapper, but I'm not really know the JSON object sending via HTTP. My original tipp was that the problem is with my JSON object. Thanks your answer Ali Dehghani!
There is no other way to send a simple Integer in POST method without use the PathVariable annotation? Are there any other de/serialization tech beside Jackson that can be deserialize a simple Integer in the request body?
Instead of application/json, you can send a key-value pair, e.g. userId=15 in the request body using application/x-www-form-urlencoded
if not @PathVariable you can use @RequestParam("userId") that will be the query parameter into URI, and will be treated as "?userId=15" a the end of the your service URI.
16

Perhaps you are trying to send a request with JSON text in its body from a Postman client or something similar like this:

{
 "userId": 3
}

This cannot be deserialized by Jackson since this is not an Integer (it seems to be, but it isn't). An Integer object from java.lang Integer is a little more complex.

For your Postman request to work, simply put (without curly braces { }):

3

2 Comments

I know this is late but how can I make my controller method to send the request like { "userId": 3 }
@Gimnath Send { "userId": "{{userIdVariable}}" }, wrapped in quotes and with no spaces between the variable name and the braces.
0

I had a similar issue and I did this (@RequestBody JsonNode json). This ensures that the information isn't passed in the url.

When you want to use the value as a number, just use: json.get(<variableName>).asInt();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.