user2581426
user2581426

Reputation: 253

JsonMappingException: Can not deserialize instance of java.lang.Integer out of START_OBJECT token

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]

Upvotes: 25

Views: 113467

Answers (3)

Eno
Eno

Reputation: 1

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();

Upvotes: 0

Javier Sanchez C
Javier Sanchez C

Reputation: 251

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

Upvotes: 16

Ali Dehghani
Ali Dehghani

Reputation: 48123

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.

Upvotes: 24

Related Questions