programing

봄 MVC: JSON 요청 본문을 역직렬화하지 않음

kakaobank 2023. 3. 23. 22:54
반응형

봄 MVC: JSON 요청 본문을 역직렬화하지 않음

Spring MVC 프로젝트를 진행하고 있는데 POST 요청 시 사용자가 JSON 데이터 문자열을 전송해야 하는 작업 중 하나입니다.Spring이 Jackson을 사용하여 오브젝트에 대한 JSON을 역직렬화한다는 것은 알고 있습니다만, 다음과 같은 것을 시도하면 다음과 같습니다.

@RequestMapping(value = "/test", method = RequestMethod.POST)
public void doSomething(@RequestBody String json) {
    // do something
}

HTTP 400 Bad Request를 돌려받기만 하면 됩니다("클라이언트에 의해 송신된 요구가 구문적으로 올바르지 않습니다.").

클라이언트가 보낸 raw JSON을 문자열로 가져오려면 어떻게 해야 하나요?

일반적으로 이러한 유형의 오류는 Spring MVC가 URL 경로와 일치하는 요청 매핑을 찾았지만 파라미터(또는 헤더 등)가 핸들러 메서드가 기대하는 것과 일치하지 않을 때 발생합니다.

@RequestBody 주석을 사용하면 Spring MVC는 POST 요청의 본문 전체를 객체에 매핑할 것으로 예상됩니다.네 몸은 단순한 스트링이 아니라 완전한 JSON 객체일 거야

JSON 오브젝트의 Java 모델이 있는 경우 String 파라미터를 doSomething 선언의 파라미터로 대체할 수 있습니다.

public void doSomething(@RequestBody MyObject myobj) {

JSON과 일치하는 Java 객체가 없는 경우 JSON을 대체하여 동작을 시도할 수 있습니다.String로 타이핑하다Map<String, Object>그 결과, 실제의 솔루션에 가까워질 수 있는지 어떤지를 확인할 수 있습니다.

Spring MVC에서 디버깅로깅을 켜면 부정한 요청의 이유에 대한 자세한 정보를 얻을 수 있습니다.

편집: 코멘트의 요건을 지정하면, Http Servlet Request 를 메서드에 삽입해, 본문을 직접 읽어낼 수 있습니다.

public void doSomething(HttpServletRequest request) {
  String jsonBody = IOUtils.toString( request.getInputStream());
  // do stuff
}

POST 본체에 매핑하는 컨트롤러 방식이나 raw String만 원하는 방식을 원하는 상황이 있었습니다.를 사용하여 이를 수행하려면@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>

그런 다음 다양한 메서드에 대한 요구는 적절한 값으로 "content-type" 헤더를 지정해야 합니다.요청 본문이 JAXB bean에 매핑되는 메서드의 경우 "를 지정합니다.application/xml". 요청 본문이 String인 경우 "를 사용합니다.text/plain".

피하려고 노력해도 돼@RequestBody를 통해 직접 요청 본문을 붙잡습니다.InputStream/Reader ★★★WebRequest/HttpServletRequest.

제 경우 json이 필드 이름을 따옴표로 묶지 않았기 때문입니다.예를 들어, 이것은 받아들여지지 않습니다.

{ entity: "OneEntity"} 

하지만 이건 그렇다.

{ "entity": "OneEntity"}

스프링 컨텍스트에서 객체 매핑을 구성하는 방법을 아직 찾지 못했습니다.JsonParser가 있다는 것을 알고 있습니다.특징.ALLOW_UNQUPORTED_FILD_NAMES는 객체 매퍼에 대해 어떻게 설정했는지 모르겠습니다.

콘텐츠 유형이 "application/json"이고 첫 번째 messageConverter가 org.springframework.http.converter가 아닌 경우.StringHttpMessageConverter , 스프링이 제대로 작동하지 않았습니다.제 경우, 다음과 같이 했습니다.

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

봄 버전 업데이트를 하는 저에게 있어서, 그것은 단지 "지금 필요한 것"이었습니다.XXX가 아닌 XXX로 모든 것이 정상적으로 동작하고 있습니다.콘텐츠 타입 어플리케이션/json

언급URL : https://stackoverflow.com/questions/16467035/spring-mvc-doesnt-deserialize-json-request-body

반응형