web-dev-qa-db-ja.com

Spring MVC:JSONリクエスト本文をデシリアライズしません

私はSpring MVCプロジェクトに取り組んでおり、行う必要のあるタスクの1つは、POSTリクエストでユーザーが送信したJSONデータの文字列を持っている必要があります。 Jacksonを使用してオブジェクトにJSONをデシリアライズしますが、次のようなものを試してみると:

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

HTTP 400 Bad Requestを返すだけです(「クライアントから送信された要求は構文的に間違っていました。」)。

クライアントから送信された生のJSONを文字列として取得するにはどうすればよいですか?

31
Ryan Morrison

通常、Spring MVCがURLパスと一致するリクエストマッピングを見つけたが、パラメーター(またはヘッダーなど)がハンドラーメソッドが予期しているものと一致しない場合、このタイプのエラーが表示されます。

@RequestBodyアノテーションを使用する場合、Spring MVCはPOSTリクエストの本文全体をオブジェクトにマッピングすることを期待しています。あなたの本文は単なる文字列ではなく、完全なJSONオブジェクト。

期待しているJSONオブジェクトのJavaモデルがある場合は、StringパラメーターをdoSomething宣言のパラメーターに置き換えることができます。

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
}
51
digitaljoel

[〜#〜] post [〜#〜] bodyをbeansや他のメソッドにマッピングするコントローラーメソッドが必要な状況がありました生のStringが必要な場所。 @RequestBodyannotationを使用してこれを実現するには、次のような複数のメッセージコンバーターを構成する必要があります。

<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」を使用します。

6
guest

@RequestBody全体で、代わりにInputStream/ReaderまたはWebRequest/HttpServletRequestを介してリクエスト本文を直接取得します。

2
pimlottc

私の場合、jsonがフィールド名を引用していないためです。例、これは受け入れられません:

{ entity: "OneEntity"} 

しかし、これははい:

{ "entity": "OneEntity"}

Springコンテキストでオブジェクトマッピングを構成する方法をまだ見つけていません。 JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMESがあることは知っていますが、それをオブジェクトマッパーに設定する方法がわかりません。

1
Toni Gamez

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="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
wfh6732

Springバージョンの更新では、XXXの代わりに「今すぐ必要です。」「XXX」であり、すべてが正常に機能しています。Content-Type application/json

0
user5101998