POST JSONが415 Unsupported media type、Spring 3 mvcで失敗する


171

POSTリクエストをサーブレットに送信しようとしています。リクエストは次のようにjQuery経由で送信されます。

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

ここでnewCategoryは

function newCategory(productCategory)
{
  $.postJSON("ajax/newproductcategory", productCategory, function(
      idProductCategory)
  {
    console.debug("Inserted: " + idProductCategory);
  });
}

そしてpostJSONは

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

firebugを使用すると、JSONが正しく送信されることがわかります。

{"idProductCategory":1,"description":"Descrizione2"}

しかし、415 Unsupported media typeが表示されます。Spring mvcコントローラーには署名があります

    @RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody
Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

数日前は機能しましたが、今は機能しません。必要に応じて、より多くのコードを表示します。ありがとう


数日前から何を変えましたか?また、var productCategory = { idProductCategory: 1, description: "Descrizione2" };もっと簡潔で読みやすいと思いませんか?Springにapplication/json具体的に受け入れるように指示する必要がありますか?言い換えれば、データがフォームで提供されることを期待していますか?
デイブニュートン

このプロジェクトの他の部分で作業して以来、多くのことがありましたが、今日、この回帰を発見しました。この部分では、何も変更しませんでした。はい、フォームから入力を得ているため、この方法を使用する必要があります。
gc5 2012

いいえ、そうではありません。JSONAjaxポストから取得しています。これは、フォームエンコードされたデータとは異なります。
デイブニュートン

1
ジャクソンがあなたのCLASSPATHでまだ利用できると確信していますか?
Tomasz Nurkiewicz

1
application / jsonの代わりにtext / jsonを送信すると、同じエラーが発生します
Blacksonic

回答:


249

これは、Spring @ResponseBodyで以前に発生したことがあります。これは、要求で送信されたAcceptヘッダーがなかったためです。AcceptヘッダーはjQueryで設定するのが面倒な場合がありますが、これは私のソースではうまくいきました

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json' 
    },
    'type': 'POST',
    'url': url,
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

Content-Typeヘッダーは、リクエストでクライアントから送信されるデータの形式を決定するために@RequestBodyによって使用されます。Acceptヘッダーは、@ ResponseBodyによって使用され、応答でクライアントにデータを送信するためのフォーマットを決定します。そのため、両方のヘッダーが必要です。


1
ヘッダー:{...}とJSON.stringify(...)は常に私をつまずきます。
Tim Perry、

1
これがもっと文書化されていない理由はわかりません。この問題は私に多くの時間を浪費させました。どうもありがとうございました!
Hugo Nava Kopp、2016年

Springはデフォルトでフォームデータをサポートすると思っていましたが、サポートしていません。(現在はかなり古い)ソリューションに感謝します。
RiZKiT

私はポストマンを使用してputリクエストを作成していましたが、content-typeを追加しました: '' application / json "ありがとう
Janatbek Sharsheyev


18

同様の問題がありましたが、問題は、@ RequestBodyで注釈が付けられたDTOのデフォルトコンストラクターの提供を怠っていたことです。


同じことが私にも起こりました。同じ名前のメソッドが2つあり、415になりました。ありがとうございます。
Daniel Vilas-Boas

12

私はまったく同じ問題に遭遇したと思います。JSON、JavaScript、サーバーとの数え切れないほどの戦いの末、犯人を見つけました:私の場合、DTOにDateオブジェクトがあり、このDateオブジェクトは文字列に変換されたので、形式:HH:mm。

JSON情報が送り返されたとき、この日付文字列オブジェクトは完全な日付オブジェクトに変換し直す必要があったため、DTOでそれを設定するメソッドも必要です。ただし、異なるタイプのパラメーター(文字列と日付)があっても、DTOに同じ名前(オーバーロード)の2つのメソッドを含めることはできません。これにより、415 Unsupported Media typeエラーも発生します。

これは私のコントローラーメソッドでした

  @RequestMapping(value = "/alarmdownload/update", produces = "application/json", method = RequestMethod.POST)
  public @ResponseBody
  StatusResponse update(@RequestBody AlarmDownloadDTO[] rowList) {
    System.out.println("hola");
    return new StatusResponse();
  }

これは私のDTOの例です(id get / setおよびpreAlarm getメソッドはコードの短縮のために含まれていません)。

@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmDownloadDTO implements Serializable {

  private static final SimpleDateFormat formatHHmm = new SimpleDateFormat("HH:mm");

  private String id;
  private Date preAlarm;

  public void setPreAlarm(Date date) { 
    this.preAlarm == date;
  }
  public void setPreAlarm(String date) {    
    try {
      this.preAlarm = formatHHmm.parse(date);
    } catch (ParseException e) {
      this.preAlarm = null;
    } catch (NullPointerException e){
      this.preAlarm = null;
    }
  }
}

すべてを機能させるには、Date型パラメーターを持つメソッドを削除する必要があります。このエラーは非常にイライラします。これが誰かのデバッグの時間を節約できることを願っています。


ありがとうございます。または、セッターの1つの名前を変更できます。私はBeanに両方のpublic void setParameters(List<Parameter> parameters)public void setParameters(Parameter... parameters)メソッドを使用し、後者を変更しaddParametersて問題を解決しました。
Conor Svensson、2015

本体がthis.preAlarm = dateではなくthis.preAlarm == dateであるという問題ではありませんか?
マイケルがモニカチェリオを2016

12

私は同様の問題に直面し、これが私がそれを修正した方法です、

問題は、JSONからJavaへの変換プロセスが原因です。正しく変換するには、適切なランタイムジャクソンライブラリが必要です。

以下のjarを追加します(依存関係を使用するか、ダウンロードしてクラスパスに追加します)。

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

これで問題が解決します。

完全なコード:

function() {
  $.ajax({
    type: "POST",
    url: "saveUserDetails.do",
    data: JSON.stringify({
      name: "Gerry",
      ity: "Sydney"
    }),
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    success: function(data) {
      if (data.status == 'OK')
        alert('Person has been added');
      else
        alert('Failed adding person: ' + data.status + ', ' + data.errorMessage);
}

コントローラのシグネチャは次のようになります。

@RequestMapping(value = "/saveUserDetails.do", method = RequestMethod.POST)
public @ResponseBody Person addPerson( @RequestBody final  Person person) {

お役に立てれば


のみjackson-databind必要です。
Alex78191 2017年

8

Spring MVCとSpring Bootを統合したときにこの問題に直面しました。これらの依存関係を追加するだけで解決しました。

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

5

小さな注意点-Webアプリケーションの開発中にこの同じエラーに遭遇しました。Firefox Posterを使用してサービスをいじったところ、Jsonのフィールドと値の両方が二重引用符で囲まれるべきであることがわかりました。例えば..

[ {"idProductCategory" : "1" , "description":"Descrizione1"}, 
  {"idProductCategory" : "2" , "description":"Descrizione2"} ]

私たちの場合、JavaScriptを介してjsonを入力しました。これは、私が聞いたことから、単一引用符または二重引用符の処理に関しては少し混乱する可能性があります。

'Accept'ヘッダーや 'Content-Type'ヘッダーを含めるなど、この記事や他の投稿で以前に述べられたことも適用されます。

お役に立てば幸いです。


3

私はそれを機能させる方法をなんとかしました。私が間違っている場合に備えて教えてください。シリアライズ/デシリアライズに1つの方法のみを使用しました。これ(@JSONSerializeおよび@JSONDeserialize)に関するすべての注釈と、CustomObjectMapperクラスに登録されたシリアライザーとデシリアライザーを削除しました。この動作を説明する記事は見つかりませんでしたが、この方法で解決しました。お役に立てれば幸いです。


私にも同じことが起こります!それが起こる理由は何ですか?
Whimusical、2015年

あなたの方法を詳しく説明していただけますか?
Dipanshu Verma 2017

1

私も同じ問題を抱えていました。この問題を解決するには、次の手順を実行する必要がありました。

1.次の依存関係があることを確認します。

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>

2.次のフィルターを作成します。

    public class CORSFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {

            String origin = request.getHeader("origin");
            origin = (origin == null || origin.equals("")) ? "null" : origin;
            response.addHeader("Access-Control-Allow-Origin", origin);
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, DELETE, OPTIONS");
            response.addHeader("Access-Control-Allow-Credentials", "true");
            response.addHeader("Access-Control-Allow-Headers",
                    "Authorization, origin, content-type, accept, x-requested-with");

            filterChain.doFilter(request, response);
        }
    }

3. web.xmlのリクエストに上記のフィルターを適用します

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>com.your.package.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

これが誰かのお役に立てば幸いです。


jackson-core依存関係jackson-databindあるため、直接追加する必要はありません。
Alex78191 2017年

1
CORSフィルターを追加する必要があるのはなぜですか?
Alex78191 2017年

1

Spring Boot + Spring MVN

問題あり

@PostMapping("/addDonation")
public String addDonation(@RequestBody DonatorDTO donatorDTO) {

ソリューションあり

@RequestMapping(value = "/addDonation", method = RequestMethod.POST)
@ResponseBody
public GenericResponse addDonation(final DonatorDTO donatorDTO, final HttpServletRequest request){

0

私のpomにjackson-jsonデータバインディングを追加することで、この問題を解決しました。

<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.3</version>
</dependency>

0

モデルクラスにjsonプロパティアノテーションを追加し、デフォルトのコンストラクターも用意する

@JsonProperty("user_name")
private String userName;

@JsonProperty("first_name")
private String firstName;

@JsonProperty("last_name")
private String lastName;

0

同じ問題がありました。追加

<mvc:annotation-driven />
<mvc:default-servlet-handler />

spring-xmlにそれを解決しました


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.