Reading Content-Type application/json in Spring

19,524

From Spring REST guide:

The Accept and Content-Type HTTP headers can be used to describe the content being sent or requested within an HTTP request. The client may set Accept to application/json if it is requesting a response in JSON. Conversely, when sending data, setting the Content-Type to application/xml tells the client that the data being sent in the request is XML.

It appears your Controller is processing only Accept header:

@RequestMapping(value = "/deepdefinitions", method = POST, headers = "Accept=application/json")

You need to change it to:

@RequestMapping(value = "/deepdefinitions", method = POST, headers = "Accept=application/json, Content-type=application/json")

There are also consumes and produces elements available in @RequestMapping annotation.

The Spring MVC documentation recommends:

Although you can match to Content-Type and Accept header values using media type wild cards (for example "content-type=text/*" will match to "text/plain" and "text/html"), it is recommended to use the consumes and produces conditions respectively instead. They are intended specifically for that purpose.


Going by your related post, you should change your method signature to:

@ResponseBody
public Definitions createOrUpdateDefinitions(@RequestBody String value, HttpEntity<String> httpEntity) throws IOException

I think you should also change you curl command as below. This is because {}(JavaScript Object literal) would map to a object and to map to a String you should use a empty string '' literal.

curl -H "Content-type: application/json" -X POST -d '' http://localhost:8080/deepdefinitions
Share:
19,524
Gregor
Author by

Gregor

Updated on June 28, 2022

Comments

  • Gregor
    Gregor almost 2 years

    Like in trying-to-use-spring-boot-rest-to-read-json-string-from-post I want to read a json payload from a POST request in a Spring RestController. Using the content type "text/plain" there is no problem, but with "application/json" the deserialization fails and I get a MessageNotReadable exception. But actually the content couldn't be simpler, it is just an empty json object "{}". Could it be that a required converter is missing? I use Spring Root version 1.2.3.RELEASE.

    Coding Example

    @RequestMapping(value = "/deepdefinitions", method = POST, headers = "Accept=application/json")
    @ResponseBody
    public Definitions createOrUpdateDefinitions(HttpEntity<String> httpEntity) throws IOException { ... }
    

    Curl Call

    curl -H  "Content-type: application/json" -X POST -d '{}' http://localhost:8080/deepdefinitions
    

    Error

    {"timestamp":1434397457853,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: org.apache.catalina.connector.CoyoteInputStream@122f9ce3; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: org.apache.catalina.connector.CoyoteInputStream@122f9ce3; line: 1, column: 1]","path":"/deepdefinitions"}
    
    • Darshan
      Darshan almost 9 years
      You should use headers = "Accept=application/json" in '@RequestMapping' and pass the serialized object in '@RequestBody' to your controller method
    • ci_
      ci_ almost 9 years
      Show the exact exception/stack trace please.
    • Gregor
      Gregor almost 9 years
      @Darshan, the "headers" in RequestMapping does not change the behaviour. I update the question with a coding example.
  • Gregor
    Gregor almost 9 years
    I had used the consumes condition before. It was Darsham who recommended to use the accept header. But the consumes leads to the same problem.