Spring MVC: Doesn't deserialize JSON request body

前端 未结 6 1405
忘掉有多难
忘掉有多难 2020-12-02 09:28

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 Spri

相关标签:
6条回答
  • 2020-12-02 09:46

    You could try avoiding @RequestBody altogether and instead grab the request body directly through a InputStream/Reader or a WebRequest/HttpServletRequest.

    0 讨论(0)
  • 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

    0 讨论(0)
  • 2020-12-02 09:57

    In my case is because the json has not quoted the field names. An example, this is not accepted:

    { 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.

    0 讨论(0)
  • 2020-12-02 09:57

    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:

    <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>

    0 讨论(0)
  • 2020-12-02 10:01

    We had a situation where we wanted some controller methods to map the POST body 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...

    <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>
    

    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".

    0 讨论(0)
  • 2020-12-02 10:06

    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.

    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.

    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

    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.

    You could also turn on debug logging in Spring MVC to get more information on why it was a bad request.

    Edit: Given your requirements in the comments, you could simply inject the HttpServletRequest into your method and read the body yourself.

    public void doSomething(HttpServletRequest request) {
      String jsonBody = IOUtils.toString( request.getInputStream());
      // do stuff
    }
    
    0 讨论(0)
提交回复
热议问题