JsonMappingException: Aucun constructeur approprié trouvé pour le type : impossible d’instancier à partir d’un object JSON

J’obtiens l’erreur suivante lorsque j’essaie d’obtenir une requête JSON et la traite:

org.codehaus.jackson.map.JsonMappingException: Aucun constructeur approprié trouvé pour le type [type simple, classe com.myweb.ApplesDO]: impossible d’instancier à partir d’un object JSON (besoin d’append / d’activer des informations de type?)

Voici le JSON que j’essaye d’envoyer:

{ "applesDO" : [ { "apple" : "Green Apple" }, { "apple" : "Red Apple" } ] } 

Dans Controller, j’ai la signature de méthode suivante:

 @RequestMapping("showApples.do") public Ssortingng getApples(@RequestBody final AllApplesDO applesRequest){ // Method Code } 

AllApplesDO est un emballage d’ApplesDO:

 public class AllApplesDO { private List applesDO; public List getApplesDO() { return applesDO; } public void setApplesDO(List applesDO) { this.applesDO = applesDO; } } 

PommesDO:

 public class ApplesDO { private Ssortingng apple; public Ssortingng getApple() { return apple; } public void setApple(Ssortingng appl) { this.apple = apple; } public ApplesDO(CustomType custom){ //constructor Code } } 

Je pense que Jackson est incapable de convertir JSON en objects Java pour les sous-classes. S’il vous plaît aider avec les parameters de configuration pour Jackson pour convertir JSON en objects Java. J’utilise le framework Spring.

EDIT: Inclusion du bug majeur qui est à l’origine de ce problème dans l’exemple de classe ci-dessus – Veuillez regarder la réponse acceptée pour la solution.

    Donc, finalement, j’ai réalisé quel était le problème. Ce n’est pas un problème de configuration Jackson, comme je le doutais.

    En fait, le problème était dans la classe ApplesDO :

     public class ApplesDO { private Ssortingng apple; public Ssortingng getApple() { return apple; } public void setApple(Ssortingng apple) { this.apple = apple; } public ApplesDO(CustomType custom) { //constructor Code } } 

    Un constructeur personnalisé a été défini pour la classe, ce qui en fait le constructeur par défaut. L’introduction d’un constructeur factice a fait l’erreur de disparaître:

     public class ApplesDO { private Ssortingng apple; public Ssortingng getApple() { return apple; } public void setApple(Ssortingng apple) { this.apple = apple; } public ApplesDO(CustomType custom) { //constructor Code } //Introducing the dummy constructor public ApplesDO() { } } 

    Cela se produit pour les raisons suivantes:

    1. votre classe interne devrait être définie comme statique

       private static class Condition { //jackson specific } 
    2. Il se peut que vous n’ayez pas de constructeur par défaut dans votre classe ( UPDATE: cela ne semble pas être le cas)

       private static class Condition { private Long id; public Condition() { } // Setters and Getters } 
    3. Il se peut que vos Setters ne soient pas définis correctement ou ne soient pas visibles (par exemple, setter privé)

    Je voudrais append une autre solution à cela qui ne nécessite pas de constructeur factice. Comme les constructeurs factices sont un peu désordonnés et par la suite déroutants. Nous pouvons fournir un constructeur sûr et en annotant les arguments du constructeur, nous permettons à jackson de déterminer le mappage entre le paramètre du constructeur et le champ.

    donc ce qui suit fonctionnera également. Notez que la chaîne à l’intérieur de l’annotation doit correspondre au nom du champ.

     import com.fasterxml.jackson.annotation.JsonProperty; public class ApplesDO { private Ssortingng apple; public Ssortingng getApple() { return apple; } public void setApple(Ssortingng apple) { this.apple = apple; } public ApplesDO(CustomType custom){ //constructor Code } public ApplesDO(@JsonProperty("apple")Ssortingng apple) { } } 

    Lorsque je me suis heurté à ce problème, c’était le résultat de l’utilisation d’une classe interne pour servir de DO. La construction de la classe interne (en silence) nécessitait une instance de la classe englobante – qui n’était pas disponible pour Jackson.

    Dans ce cas, le déplacement de la classe interne vers son propre fichier .java a résolu le problème.

    Pouvez-vous s’il vous plaît tester cette structure. Si je me souviens bien, vous pouvez l’utiliser de cette façon:

     { "applesRequest": { "applesDO": [ { "apple": "Green Apple" }, { "apple": "Red Apple" } ] } } 

    Deuxièmement, ajoutez un constructeur par défaut à chaque classe.

    Règle de pouce : Ajoutez un constructeur par défaut pour chaque classe que vous avez utilisée comme classe de mappage. Vous avez manqué cela et le problème se pose!
    Ajoutez simplement le constructeur par défaut et cela devrait fonctionner.

    Vous devez créer un constructeur vide factice dans notre classe de modèle. Ainsi, lors du mappage de json, il est défini par la méthode setter.

    Si vous commencez à annoter le constructeur, vous devez annoter tous les champs.

    Notez que mon champ Staff.name est mappé sur “ANOTHER_NAME” dans la chaîne JSON.

      Ssortingng jsonInSsortingng="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}"; ObjectMapper mapper = new ObjectMapper(); Staff obj = mapper.readValue(jsonInSsortingng, Staff.class); // print to screen public static class Staff { public Ssortingng name; public Integer age; public Staff() { } //@JsonCreator - don't need this public Staff(@JsonProperty("ANOTHER_NAME") Ssortingng n,@JsonProperty("age") Integer a) { name=n;age=a; } } 

    Vous devez savoir quelles options Jackson a disponibles pour la désérialisation. En Java, les noms d’argument de méthode ne sont pas présents dans le code compilé. C’est pourquoi Jackson ne peut généralement pas utiliser les constructeurs pour créer un object bien défini avec tout ce qui est déjà défini.

    Donc, s’il y a un constructeur vide et qu’il y a aussi des setters, il utilise le constructeur et les setters vides. S’il n’y a pas de régleur, de la magie noire (reflections) est utilisée pour le faire.

    Si vous voulez utiliser un constructeur avec Jackson, vous devez utiliser les annotations mentionnées par @PiersyP dans sa réponse. Vous pouvez également utiliser un modèle de générateur. Si vous rencontrez des exceptions, bonne chance. La gestion des erreurs dans Jackson est une tâche difficile, il est difficile de comprendre ce charabia dans les messages d’erreur.

    Échec de Serializers / Deserializers personnalisé jackson pourrait également être le problème. Bien que ce ne soit pas votre cas, cela vaut la peine de le mentionner.

    J’ai fait face à la même exception et c’était le cas.

    Pour moi, cela fonctionnait, mais la mise à niveau des bibliothèques a provoqué l’apparition de ce problème. Le problème était d’avoir une classe comme celle-ci:

     package example.counter; import javax.validation.constraints.NotNull; import lombok.Data; @Data public class CounterRequest { @NotNull private final Integer int1; @NotNull private final Integer int2; } 

    En utilisant lombok:

      org.projectlombok lombok 1.18.0  

    Revenir à

      org.projectlombok lombok 1.16.10  

    Correction du problème. Je ne sais pas pourquoi, mais je voulais le documenter pour le futur.