195 votes

POST JSON échoue avec 415 non pris en charge type de média, Spring mvc 3

J'essaie d'envoyer une requête POST à une servlet. La demande est envoyée via jQuery de cette façon:

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

où est newCategory

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

et postJSON est

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

Avec firebug je vois que JSON est envoyé correctement:

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

Mais j'ai 415 non pris en charge type de média. Spring mvc contrôleur a la signature

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

Il y a quelques jours, il a travaillé, maintenant il ne l'est pas. Je vais vous montrer plus de code si nécessaire. Merci

273voto

theon Points 3895

J'ai eu cela avant le Printemps @ResponseBody et c'était parce qu'il n'y a pas d'en-tête accept envoyé avec la demande. Accepter d'en-tête peut être une douleur à définir avec jQuery, mais cela a fonctionné pour moi source

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

Le Type de Contenu de l'en-tête est utilisé par @RequestBody pour déterminer le format des données envoyées par le client dans la demande. L'en-tête accept est utilisé par @ResponseBody pour déterminer quel format pour envoyer les données vers le client dans la réponse. C'est pourquoi vous avez besoin à la fois d'en-têtes.

18voto

John Shepherd Points 51

J'ai eu un problème similaire mais le problème était que j'avais négligé de fournir un constructeur par défaut pour la DTO qui a été annotée avec @RequestBody.

12voto

will824 Points 735

Je crois que j'ai couru exactement dans le même problème. Après d'innombrables heures de combat avec hein JSon, Javascript et le Serveur, j'ai trouvé le coupable: Dans mon cas, j'ai eu une Date objet de la DTO, à cette Date, objet était converti en Chaîne de caractères à afficher dans la vue dans le format suivant: HH:mm.

Le problème était que lorsque JSon a été l'envoi en retour l'information, à cette Date, l'objet devait être convertie en un objet Date, par conséquent, vous avez besoin d'une méthode pour définir dans la DTO. La grande MAIS vous ne pouvez pas avoir 2 méthodes avec le même nom dans la DTO parce que vous obtiendrez le fameux 415 Unsupported Media type d'erreur.

C'était ma méthode de contrôleur

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

C'était mon DTO exemple (id get/set et preAlarm Méthodes get ne sont pas inclus dans le code essoufflement):

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

Pour que tout fonctionne, vous devez supprimer le deuxième Date de la méthode (l'un avec la Date, le type de paramètre). Cette erreur est très frustrant. J'espère que cela va aider quelqu'un à des heures de débogage.

5voto

Carlos Romero Points 23

Une petite note de côté - tombé sur cette même erreur lors du développement d'une application web. L'erreur que nous avons trouvé, par jongle avec le service avec Firefox Affiche, a été que les deux champs et des valeurs dans le Json doit être entouré par des guillemets. Par exemple..

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

Dans notre cas, nous avons rempli le json via javascript, qui peut être un peu confus quand il s'agit de traiter avec simple/double guillemets, de ce que j'ai entendu.

Ce qui a été dit avant dans ce domaine et dans d'autres postes, comme notamment la "Accepter" et "Content-Type" en-têtes, s'applique aussi.

Espère t'helps.

3voto

nsl Points 1058

J'ai réussi à rendre cela fonctionne. Dites-moi au cas où je me trompe. J'ai utilisé une seule façon de sérialiser/désérialiser: j'ai enlevé toutes les annotations concernant cette (@JSONSerialize et @JSONDeserialize) et les Sérialiseurs et Deserializers en CustomObjectMapperclasse. Je n'ai pas trouvé un article expliquant ce comportement, mais je résolus de cette façon. J'espère que c'est utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X