Java Spring MVC:不反序列化 JSON 请求正文
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16467035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring MVC: Doesn't deserialize JSON request body
提问by Ryan Morrison
I'm working on a Spring MVC project and one of the tasks I need to do requires me to have a string of JSON data sent through by the user in a POST request. I know that Spring will deserialize JSON using Hymanson to objects, but if I try something like the following:
我正在处理一个 Spring MVC 项目,我需要做的任务之一要求我拥有用户在 POST 请求中发送的一串 JSON 数据。我知道 Spring 会使用 Hymanson 将 JSON 反序列化为对象,但是如果我尝试以下操作:
@RequestMapping(value = "/test", method = RequestMethod.POST)
public void doSomething(@RequestBody String json) {
// do something
}
I simply get HTTP 400 Bad Request back ("The request sent by the client was syntactically incorrect.").
我只是返回 HTTP 400 Bad Request(“客户端发送的请求在语法上不正确。”)。
How can I get the raw JSON sent by the client as a string?
如何将客户端发送的原始 JSON 作为字符串获取?
采纳答案by digitaljoel
You will usually see this type of error when Spring MVC finds a request mapping that matches the URL path but the parameters (or headers or something) don't match what the handler method is expecting.
当 Spring MVC 找到与 URL 路径匹配的请求映射但参数(或标头或其他东西)与处理程序方法所期望的不匹配时,您通常会看到这种类型的错误。
If you use the @RequestBody annotation then I believe Spring MVC is expecting to map the entire body of the POST request to an Object. I'm guessing your body is not simply a String, but some full JSON object.
如果您使用 @RequestBody 注释,那么我相信 Spring MVC 期望将 POST 请求的整个主体映射到一个对象。我猜你的身体不仅仅是一个字符串,而是一些完整的 JSON 对象。
If you have a java model of the JSON object you are expecting then you could replace the String parameter with that in your doSomething declaration, such as
如果您有您期望的 JSON 对象的 Java 模型,那么您可以将字符串参数替换为 doSomething 声明中的参数,例如
public void doSomething(@RequestBody MyObject myobj) {
public void doSomething(@RequestBody MyObject myobj) {
If you don't have a Java object that matches the JSON then you could try to get it working by replacing the String
type with a Map<String, Object>
and see if that gets you closer to a working solution.
如果您没有与 JSON 匹配的 Java 对象,那么您可以尝试通过将String
类型替换为a来使其工作,Map<String, Object>
并查看这是否能让您更接近工作解决方案。
You could also turn on debug logging in Spring MVC to get more information on why it was a bad request.
您还可以在 Spring MVC 中打开调试日志记录以获取有关为什么这是错误请求的更多信息。
Edit:Given your requirements in the comments, you could simply inject the HttpServletRequest into your method and read the body yourself.
编辑:根据您在评论中的要求,您可以简单地将 HttpServletRequest 注入您的方法并自己阅读正文。
public void doSomething(HttpServletRequest request) {
String jsonBody = IOUtils.toString( request.getInputStream());
// do stuff
}
回答by pimlottc
You could try avoiding @RequestBody
altogether and instead grab the request body directly through a InputStream
/Reader
or a WebRequest
/HttpServletRequest
.
您可以尝试@RequestBody
完全避免,而是直接通过InputStream
/Reader
或WebRequest
/获取请求正文HttpServletRequest
。
回答by Toni Gamez
In my case is because the json has not quoted the field names. An example, this is not accepted:
就我而言,是因为 json 没有引用字段名称。一个例子,这是不被接受的:
{ entity: "OneEntity"}
but this one yes:
但这个是的:
{ "entity": "OneEntity"}
I haven't found yet how I can configure object mapping in spring context. I know there is a JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES but I don't know how set that for object mapper.
我还没有找到如何在 spring 上下文中配置对象映射。我知道有一个 JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES 但我不知道如何为对象映射器设置它。
回答by guest
We had a situation where we wanted some controller methods to map the POSTbody to beans, and other methods where we just wanted the raw String. To accomplish this using the @RequestBody
annotation, you need to configure multiple message converters, something like...
我们有一种情况,我们需要一些控制器方法将POST主体映射到bean,而其他方法我们只需要原始String。要使用@RequestBody
annotation完成此操作,您需要配置多个消息转换器,例如...
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
<ref bean="marshallingConverter" />
<ref bean="stringHttpMessageConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingHymansonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
<bean id="marshallingConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxb2Marshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/plain"/>
</bean>
Then, requests to the various methods must specify the "content-type" header with an appropriate value. For those methods where the request body is mapped to a JAXB bean, specify "application/xml
". And for those where the request body is a String, use "text/plain
".
然后,对各种方法的请求必须指定具有适当值的“内容类型”标头。对于那些将请求主体映射到JAXB bean 的方法,请指定“ application/xml
”。对于请求正文是String 的那些,请使用“ text/plain
”。
回答by wfh6732
if your Content-type is "application/json" and your first messageConvertor is not org.springframework.http.converter.StringHttpMessageConverter , Spring could not work right. In my case , I did this:
如果您的 Content-type 是“application/json”并且您的第一个 messageConvertor 不是 org.springframework.http.converter.StringHttpMessageConverter ,则 Spring 无法正常工作。就我而言,我这样做了:
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="stringHttpMessageConverter" /><!-- 放在前面,对@RequestBody String json 提供支持 -->
<ref bean="mappingHymansonHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 消息转换器 -->
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text" />
<constructor-arg index="1" value="plain" />
<constructor-arg index="2" value="UTF-8" />
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application" />
<constructor-arg index="1" value="json" />
<constructor-arg index="2" value="UTF-8" />
</bean>
</list>
</property>
</bean>
<bean id="mappingHymansonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingHymanson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text" />
<constructor-arg index="1" value="plain" />
<constructor-arg index="2" value="UTF-8" />
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application" />
<constructor-arg index="1" value="json" />
<constructor-arg index="2" value="UTF-8" />
</bean>
</list>
</property>
<!-- 设置时间格式, 有了这个就不用在pojo的属性上写了 -->
<property name="objectMapper">
<bean class="com.fasterxml.Hymanson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"></constructor-arg>
</bean>
</property>
</bean>
</property>
</bean>
回答by user5101998
For me with spring version update it was simply an " necessary now. "XXX" instead of XXX and everything is working fine as you have it. Content-Type application/json
对我来说,spring 版本更新只是一个“现在必需的”。“XXX”而不是 XXX,一切正常,因为你拥有它。内容类型应用程序/json