我正在开发一个Spring MVC项目,我需要完成的任务之一要求我在POST请求中通过用户发送一串JSON数据。我知道Spring会使用Jackson将JSON反序列化为对象,但如果我尝试以下内容:
@RequestMapping(value = "/test", method = RequestMethod.POST)
public void doSomething(@RequestBody String json) {
// do something
}
我只是回复了HTTP 400错误请求(“客户端发送的请求在语法上不正确。”)。
如何将客户端发送的原始JSON作为字符串?
答案 0 :(得分:50)
当Spring MVC找到与URL路径匹配的请求映射但参数(或标题或其他内容)与处理程序方法所期望的不匹配时,您通常会看到此类错误。
如果您使用@RequestBody注释,那么我相信Spring MVC期望将POST请求的整个主体映射到Object。我猜你的身体不仅仅是一个字符串,而是一些完整的JSON对象。
如果你有一个期望的JSON对象的java模型,那么你可以用你的doSomething声明中的String参数替换它,例如
public void doSomething(@RequestBody MyObject myobj) {
如果您没有与JSON匹配的Java对象,那么您可以尝试通过将String
类型替换为Map<String, Object>
来使其工作,看看是否让您更接近一个有效的解决方案。
您还可以打开Spring MVC中的调试日志记录,以获取有关它为什么是错误请求的更多信息。
修改强> 根据您在评论中的要求,您可以简单地将HttpServletRequest注入您的方法并自己阅读正文。
public void doSomething(HttpServletRequest request) {
String jsonBody = IOUtils.toString( request.getInputStream());
// do stuff
}
答案 1 :(得分:6)
我们有一种情况,我们想要一些控制器方法将 POST 正文映射到 beans ,以及我们只想要原始字符串的其他方法。要使用@RequestBody
注释完成此操作,您需要配置多个消息转换器,例如......
<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.MappingJacksonHttpMessageConverter">
<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>
然后,对各种方法的请求必须指定&#34; 内容类型&#34;标头具有适当的值。对于请求主体映射到 JAXB bean 的那些方法,请指定&#34; application/xml
&#34;。对于请求正文为 String 的用户,请使用&#34; text/plain
&#34;。
答案 2 :(得分:2)
您可以尝试完全避免@RequestBody
,而是直接通过InputStream
/ Reader
或WebRequest
/ HttpServletRequest
抓取请求正文。
答案 3 :(得分:1)
在我的情况下是因为json没有引用字段名称。 例如,这是不被接受的:
{ entity: "OneEntity"}
但是这一个是:
{ "entity": "OneEntity"}
我还没有找到如何在spring上下文中配置对象映射。 我知道有一个JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,但我不知道如何设置对象映射器。
答案 4 :(得分:0)
如果您的内容类型是&#34; application / json&#34;而你的第一个messageConvertor不是org.springframework.http.converter.StringHttpMessageConverter,Spring无法正常工作。就我而言,我这样做了:
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="stringHttpMessageConverter" /><!-- 放在前面,对@RequestBody String json 提供支持 -->
<ref bean="mappingJacksonHttpMessageConverter" />
</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="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<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.jackson.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>
&#13;
答案 5 :(得分:0)
对于我的春季版更新,它只是一个“必要的现在。 “XXX”而不是XXX,一切正常,因为你拥有它。 Content-Type application / json