POST JSON 失败,415 Unsupported media type, Spring 3 mvc

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11492325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:27:11  来源:igfitidea点击:

POST JSON fails with 415 Unsupported media type, Spring 3 mvc

ajaxjsonspringposthttp-status-code-415

提问by gc5

I am trying to send a POST request to a servlet. Request is sent via jQuery in this way:

我正在尝试向 servlet 发送 POST 请求。请求通过 jQuery 以这种方式发送:

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

where newCategory is

newCategory 在哪里

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

and postJSON is

和 postJSON 是

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

With firebug I see that JSON is sent correctly:

使用 firebug 我看到 JSON 已正确发送:

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

But I get 415 Unsupported media type. Spring mvc controller has signature

但是我得到 415 Unsupported media type。Spring mvc 控制器有签名

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

Some days ago it worked, now it is not. I'll show more code if needed. Thanks

几天前它有效,现在它不是。如果需要,我会显示更多代码。谢谢

采纳答案by gc5

I managed out how to make it works. Tell me in case I am wrong. I used only one way to serialize/deserialize: I removed all annotations regarding this (@JSONSerializeand @JSONDeserialize) and registered Serializers and Deserializers in CustomObjectMapperclass. I didn't find an article explaining this behaviour but I resolved in this way. Hope it's useful.

我设法使它起作用。如果我错了,请告诉我。我只使用了一种序列化/反序列化的方法:我删除了关于 this ( @JSONSerializeand @JSONDeserialize) 的所有注释,并在CustomObjectMapper类中注册了 Serializers 和 Deserializers 。我没有找到解释这种行为的文章,但我以这种方式解决了。希望它有用。

回答by theon

I've had this happen before with Spring @ResponseBody and it was because there was no accept header sent with the request. Accept header can be a pain to set with jQuery, but this worked for me source

我之前在 Spring @ResponseBody 上发生过这种情况,这是因为没有随请求发送的接受标头。使用 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
    });
};

The Content-Type header is used by @RequestBody to determine what format the data being sent from the client in the request is. The accept header is used by @ResponseBody to determine what format to sent the data back to the client in the response. That's why you need both headers.

@RequestBody 使用 Content-Type 标头来确定请求中从客户端发送的数据的格式。@ResponseBody 使用接受标头来确定在响应中将数据发送回客户端的格式。这就是为什么你需要两个标题。

回答by uiroshan

adding content type into the request as application/jsonresolved the issue

将内容类型添加到请求中以application/json解决问题

回答by John Shepherd

I had a similar problem but found the issue was that I had neglected to provide a default constructor for the DTO that was annotated with @RequestBody.

我有一个类似的问题,但发现问题是我忽略了为使用 @RequestBody 注释的 DTO 提供默认构造函数。

回答by will824

I believe I ran exactly into the same issue. After countless hours of fighting with the JSON, the JavaScript and the Server, I found the culprit: In my case I had a Date object in the DTO, this Date object was converted to a String so we could show it in the view with the format: HH:mm.

我相信我遇到了完全相同的问题。在与 JSON、JavaScript 和服务器进行了无数小时的斗争之后,我找到了罪魁祸首:在我的例子中,我在 DTO 中有一个 Date 对象,这个 Date 对象被转换为一个 String,因此我们可以在视图中显示它格式:HH:mm。

When JSON information was being sent back, this Date String object had to be converted back into a full Date Object, therefore we also need a method to set it in the DTO. The big BUT is you cannot have 2 methods with the same name (Overload) in the DTO even if they have different type of parameter (String vs Date) because this will give you also the 415 Unsupported Media type error.

当 JSON 信息被发送回来时,这个 Date String 对象必须转换回一个完整的 Date Object,因此我们还需要一个方法来在 DTO 中设置它。最重要的是,即使它们具有不同类型的参数(字符串与日期),DTO 中也不能有 2 个具有相同名称(重载)的方法,因为这也会给您 415 Unsupported Media type 错误。

This was my controller method

这是我的控制器方法

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

This was my DTO example (id get/set and preAlarm get Methods are not included for code shortness):

这是我的 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;
    }
  }
}

To make everything work you need to remove the method with Date type parameter. This error is very frustrating. Hope this can save someone hours of debugging.

为了使一切正常,您需要删除带有 Date 类型参数的方法。这个错误非常令人沮丧。希望这可以节省一些人的调试时间。

回答by vinSan

I faced a similar issue and this is how I fixed it,

我遇到了类似的问题,这就是我解决它的方法,

The problem is due to the conversion process from JSON to Java, one need to have the right run time Hymanson libraries for the conversion to happen correctly.

问题是由于从 JSON 到 Java 的转换过程,需要有正确的运行时 Hymanson 库才能正确进行转换。

Add the following jars (through dependency or by downloading and adding to the classpath.

添加以下 jars(通过依赖项或通过下载并添加到类路径。

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

This should fix the problem.

这应该可以解决问题。

Complete Code:

完整代码:

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);
}

and the controller signature looks like this:

控制器签名如下所示:

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

Hope this helps

希望这可以帮助

回答by deep

I faced this issue when I integrated spring boot with spring mvc. I solved it by just adding these dependencies.

当我将 spring boot 与 spring mvc 集成时,我遇到了这个问题。我通过添加这些依赖项解决了它。

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

回答by Carlos Romero

A small side note - stumbled upon this same error while developing a web application. The mistake we found, by toying with the service with Firefox Poster, was that both fields and values in the Json should be surrounded by double quotes. For instance..

一个小的旁注 - 在开发 Web 应用程序时偶然发现了同样的错误。通过使用 Firefox Poster 使用服务,我们发现的错误是 Json 中的字段和值都应该用双引号括起来。例如..

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

In our case we filled the json via javascript, which can be a little confusing when it comes with dealing with single/double quotes, from what I've heard.

在我们的例子中,我们通过 javascript 填充了 json,据我所知,在处理单/双引号时可能会有点混乱。

What's been said before in this and other posts, like including the 'Accept' and 'Content-Type' headers, applies too.

之前在这篇文章和其他文章中说过的内容,例如包含“接受”和“内容类型”标题,也适用。

Hope t'helps.

希望有帮助。

回答by Manoj Shrestha

I had the same problem. I had to follow these steps to resolve the issue:

我有同样的问题。我必须按照以下步骤解决问题:

1. Make sure you have the following dependencies:

1. 确保您有以下依赖项:

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

2. Create the following filter:

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. Apply the above filter for the requests in web.xml

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>

I hope this is useful to somebody.

我希望这对某人有用。

回答by Shahid Hussain Abbasi

Spring boot + spring mvn

弹簧靴 + 弹簧 mvn

with issue

有问题

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

with solution

有解决方案

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