【问题标题】:Reading Content-Type application/json in Spring在 Spring 中读取 Content-Type application/json
【发布时间】:2015-08-30 21:26:11
【问题描述】:

就像trying-to-use-spring-boot-rest-to-read-json-string-from-post 一样,我想从 Spring RestController 中的 POST 请求中读取 json 有效负载。使用内容类型“text/plain”没有问题,但使用“application/json”反序列化失败,我得到一个 MessageNotReadable 异常。但实际上内容再简单不过了,它只是一个空的 json 对象“{}”。可能是缺少所需的转换器吗? 我使用 Spring Root 版本 1.2.3.RELEASE。

编码示例

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

卷发电话

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

错误

{"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"}

【问题讨论】:

  • 您应该在 '@RequestMapping' 中使用 headers = "Accept=application/json" 并将 '@RequestBody' 中的序列化对象传递给您的控制器方法
  • 请显示确切的异常/堆栈跟踪。
  • @Darshan,RequestMapping 中的“标题”不会​​改变行为。我用一个编码示例更新了这个问题。

标签: java json spring spring-mvc spring-boot


【解决方案1】:

来自Spring REST guide

AcceptContent-Type HTTP 标头可用于描述在 HTTP 请求中发送或请求的内容。如果客户端请求 JSON 响应,则客户端可以将 Accept 设置为 application/json。反之,在发送数据时,将Content-Type设置为application/xml会告诉客户端请求中发送的数据是XML。

您的控制器似乎只处理 Accept 标头:

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

您需要将其更改为:

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

@RequestMapping 注释中还有 consumesproduces elements 可用。

Spring MVC documentation推荐:

虽然您可以使用媒体类型通配符匹配Content-TypeAccept 标头值(例如,“content-type=text/*”将匹配“text/plain”和“text/html”),建议分别使用consumesproduces 条件。它们专门用于此目的。


通过您的相关帖子,您应该将方法签名更改为:

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

我认为您还应该如下更改 curl 命令。这是因为 {}(JavaScript Object literal) 会映射到一个对象,而要映射到一个字符串,您应该使用空字符串 '' 文字。

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

【讨论】:

  • 我之前使用过消费条件。 Darsham 建议使用接受标头。但是消耗会导致同样的问题。
猜你喜欢
  • 1970-01-01
  • 2020-04-23
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 2015-10-20
  • 2018-03-17
相关资源
最近更新 更多