POST JSON eșuează cu 415 Unsupported media type, Spring 3 mvc (Programare, Ajax, Json, Spring, Posta, Cod De Stare Http 415)

gc5 a intrebat.

Încerc să trimit o cerere POST către un servlet. Cererea este trimisă prin jQuery în acest mod:

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

unde newCategory este

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

și postJSON este

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

Cu firebug văd că JSON este trimis corect:

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

Dar primesc 415 Unsupported media type. Controlerul Spring mvc are semnătura

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

Cu câteva zile în urmă a funcționat, acum nu mai este. Voi arăta mai mult cod dacă este necesar. mulțumesc

Comentarii

  • Ce ați schimbat de acum câteva zile? De asemenea, nu ar fi var productCategory = { idProductCategory: 1, description: "Descrizione2" }; fi mai concis și mai ușor de citit? Trebuie să îi spuneți lui Spring să accepte application/json în mod specific? Cu alte cuvinte, se așteaptă ca datele să vină într-un formular? –  > Por Dave Newton.
  • O mulțime de lucruri de când lucram la altă parte a acestui proiect, iar astăzi am găsit această regresie. În această parte nu am schimbat nimic. Da, trebuie să folosesc acest mod, deoarece primesc date de intrare dintr-un formular. –  > Por gc5.
  • Nu, nu este așa, îl primești de la o postare JSON Ajax, care nu este același lucru cu datele codificate în formular. –  > Por Dave Newton.
  • Sunteți sigur că Jackson este încă disponibil în CLASSPATH? –  > Por Tomasz Nurkiewicz.
  • dacă trimiteți text/json în loc de application/json primiți aceeași eroare – –  > Por Blacksonic.
14 răspunsuri
theon

Am mai pățit asta înainte cu Spring @ResponseBody și a fost din cauză că nu a fost trimis niciun antet accept împreună cu cererea. Accept header poate fi o pacoste de setat cu jQuery, dar asta a funcționat pentru mine sursa

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

Antetul Content-Type este utilizat de @RequestBody pentru a determina formatul datelor trimise de client în cerere. Antetul Accept este utilizat de @ResponseBody pentru a determina formatul în care se trimit datele înapoi la client în răspuns. De aceea aveți nevoie de ambele antete.

Comentarii

  • antetele: {…} și JSON.stringify(…) mă încurcă întotdeauna. –  > Por Tim Perry.
  • Habar nu am de ce acest lucru nu este mai documentat. Această problemă m-a făcut să pierd foarte mult timp. Vă mulțumesc foarte mult! –  > Por Hugo Nava Kopp.
  • Mă așteptam ca Spring să suporte în mod implicit datele de formular, dar nu este așa. Așadar, mulțumesc pentru soluția (acum destul de veche). –  > Por RiZKiT.
  • Foloseam un postman pentru a face o cerere de tip put, doar am adăugat content-type: ”application/json”. mulțumesc – –  > Por Janatbek Sharsheyev.
uiroshan

adăugând tipul de conținut în cerere ca application/json a rezolvat problema

John Shepherd

Am avut o problemă similară, dar am descoperit că problema a fost că am neglijat să furnizez un constructor implicit pentru DTO care a fost notat cu @RequestBody.

Comentarii

  • același lucru mi s-a întâmplat și mie. Aveam 2 metode cu același nume și primeam 415. Mulțumesc! –  > Por Daniel Vilas-Boas.
vinSan

M-am confruntat cu o problemă similară și iată cum am rezolvat-o,

Problema se datorează procesului de conversie de la JSON la Java, trebuie să aveți bibliotecile jackson de execuție corecte pentru ca conversia să se realizeze corect.

Adăugați următoarele jar-uri (prin dependență sau prin descărcare și adăugare în classpath.

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

Acest lucru ar trebui să rezolve problema.

Codul complet:

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

și semnătura controlerului arată astfel:

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

Sper că acest lucru vă ajută

Comentarii

  • Numai jackson-databind este necesar. –  > Por Alex78191.
will824

Cred că m-am lovit exact de aceeași problemă. După nenumărate ore de luptă cu JSON, JavaScript și Server, am găsit vinovatul: În cazul meu aveam un obiect Date în DTO, acest obiect Date a fost convertit într-un String pentru a-l putea afișa în vizualizare cu formatul: HH:mm.

Atunci când informațiile JSON erau trimise înapoi, acest obiect Date String trebuia să fie convertit înapoi într-un obiect Date complet, prin urmare, aveam nevoie și de o metodă pentru a-l seta în DTO. Marele BUT este că nu puteți avea 2 metode cu același nume (Overload) în DTO, chiar dacă au un tip diferit de parametru (String vs. Date), deoarece acest lucru vă va da, de asemenea, eroarea 415 Unsupported Media type.

Aceasta a fost metoda mea de controler

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

Acesta a fost exemplul meu DTO (metodele id get/set și preAlarm get nu sunt incluse pentru a scurta codul):

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

Pentru ca totul să funcționeze, trebuie să eliminați metoda cu parametrul de tip Date. Această eroare este foarte frustrantă. Sper că acest lucru poate salva pe cineva ore întregi de depanare.

Comentarii

  • Mulțumesc – sau puteți redenumi unul dintre setteri. Am avut ambele public void setParameters(List<Parameter> parameters) & public void setParameters(Parameter... parameters) într-un bean, schimbând-o pe cea din urmă în addParameters a rezolvat problema pentru mine. –  > Por Conor Svensson.
  • Problema nu este că corpul este this.preAlarm == date și nu this.preAlarm = date? –  > Por Michael restore Monica Cellio.
deep

M-am confruntat cu această problemă când am integrat spring boot cu spring mvc. Am rezolvat-o prin simpla adăugare a acestor dependențe.

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

Carlos Romero

O mică notă secundară – m-am împiedicat de aceeași eroare în timp ce dezvoltam o aplicație web. Greșeala pe care am găsit-o, jucându-ne cu serviciul cu Firefox Poster, a fost că atât câmpurile, cât și valorile din Json ar trebui să fie înconjurate de ghilimele duble. De exemplu:.

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

În cazul nostru, am completat json-ul prin javascript, care poate fi puțin confuz atunci când vine vorba de tratarea ghilimelelor simple/duble, din câte am auzit.

Ceea ce s-a spus înainte în acest articol și în alte articole, cum ar fi includerea antetelor „Accept” și „Content-Type”, se aplică și în acest caz.

Sper că vă ajută.

gc5

Am reușit cum să fac să funcționeze. Spuneți-mi în caz că greșesc. am folosit un singur mod de serializare/deserializare: Am eliminat toate adnotările referitoare la acest lucru (@JSONSerialize și @JSONDeserialize) și am înregistrat Serializatori și Deserializatori în CustomObjectMapper class.I nu am găsit un articol care să explice acest comportament, dar am rezolvat în acest fel. Sper că este util.

Comentarii

  • Se întâmplă la fel și cu mine! Vreo explicație de ce se întâmplă? –  > Por Whimusical.
  • Poți să ne explici în detaliu metoda ta, te rog? –  > Por Dipanshu Verma.
Manoj Shrestha

Am avut aceeași problemă. A trebuit să urmez acești pași pentru a rezolva problema:

1. Asigurați-vă că aveți următoarele dependențe:

    <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. Creați următorul filtru:

    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. Aplicați filtrul de mai sus pentru cererile din 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>

Sper că acest lucru este util pentru cineva.

Comentarii

  • jackson-core este un dependență de jackson-databinddeci nu este nevoie să o adăugați direct. –  > Por Alex78191.
  • De ce este necesar să adăugați filtrul CORS? –  > Por Alex78191.
Shahid Hussain Abbasi

Spring boot + spring mvn

cu problemă

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

cu soluție

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

Lingasamy Bagavathi

Am rezolvat această problemă adăugând jackson-json data binding la pomul meu.

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

deko

În clasa dvs. de model adăugați o adnotare de proprietate json, de asemenea, aveți un constructor implicit

@JsonProperty("user_name")
private String userName;

@JsonProperty("first_name")
private String firstName;

@JsonProperty("last_name")
private String lastName;

OhadR

Am avut aceeași problemă. adăugând

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

la spring-xml a rezolvat problema

Victor

1.a. Adăugați următoarele în applicationContext-mvc.xml

xmlns:mvc=”http://www.springframework.org/schema/mvc „xsi:schemaLocation=” http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc

  1. adăugați biblioteca jackson