JsonMappingException: aucun constructeur approprié trouvé pour type [simple type, class: ne peut pas instancier à partir de l'objet JSON

j'obtiens l'erreur suivante en essayant d'obtenir une requête JSON et de la traiter:

org.codehaus.Jackson.cartographie.JsonMappingException: Pas de constructeur trouvé pour le type [type simple, classe com.myweb.ApplesDO]: ne peut pas instancier à partir de l'objet JSON (besoin d'ajouter/activer des informations de type?)

voici le JSON que j'essaie d'envoyer:

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

dans Controller, j'ai le la signature de la méthode suivante:

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

AllApplesDO est un wrapper de ApplesDO :

public class AllApplesDO {

    private List<ApplesDO> applesDO;

    public List<ApplesDO> getApplesDO() {
        return applesDO;
    }

    public void setApplesDO(List<ApplesDO> applesDO) {
        this.applesDO = applesDO;
    }
}

ApplesDO:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String appl) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom){
        //constructor Code
    }
}

je pense que Jackson est incapable de convertir JSON en objets Java pour les sous-classes. S'il vous plaît aidez avec les paramètres de configuration pour Jackson pour convertir JSON en objets Java. Je suis en utilisant le Framework Spring.

EDIT: inclus le bug principal qui cause ce problème dans le au - dessus de la classe d'échantillon-s'il vous plaît regarder réponse acceptée pour la solution.

368
demandé sur Joeri Hendrickx 2011-10-02 14:16:13

12 réponses

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

en fait, le problème était dans ApplesDO Classe:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }
}

il y avait un constructeur personnalisé défini pour la classe en faisant le constructeur par défaut. L'introduction d'un constructeur fictif a fait l'erreur de disparaître:

public class ApplesDO {

    private String apple;

    public String getApple() {
        return apple;
    }

    public void setApple(String apple) {
        this.apple = apple;
    }

    public ApplesDO(CustomType custom) {
        //constructor Code
    }

    //Introducing the dummy constructor
    public ApplesDO() {
    }

}
504
répondu Lucky Murari 2014-01-22 14:56:18

cela se produit pour ces raisons:

  1. votre classe intérieure doit ê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 ( mise à jour: 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 visible (p.ex. setter privé)

337
répondu azerafati 2018-04-21 14:41:58

je voudrais ajouter une autre solution qui ne nécessite pas de constructeur fictif. Puisque les constructeurs factices sont un peu désordonnés et par la suite confus. Nous pouvons fournir un constructeur sûr et en annotant les arguments du constructeur nous permettons à jackson de déterminer la correspondance entre le paramètre constructeur et le champ.

donc la suite. Notez 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 String apple;

        public String getApple() {
            return apple;
        }

        public void setApple(String apple) {
            this.apple = apple;
        }

        public ApplesDO(CustomType custom){
            //constructor Code
        }

        public ApplesDO(@JsonProperty("apple")String apple) {
        }

}
55
répondu PiersyP 2014-11-26 12:15:14

quand je suis tombé sur ce problème, c'était le résultat d'essayer d'utiliser une classe intérieure pour servir comme le faire. La Construction de la classe intérieure (silencieusement) a exigé une instance de la classe enclosante-qui n'était pas disponible pour Jackson.

dans ce cas, faire passer la classe intérieure à elle-même .fichier java résolu le problème.

27
répondu jmarks 2015-09-17 01:01:17

pouvez-vous tester cette structure? Si je me souviens correct vous pouvez l'utiliser de cette façon:

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

en Second lieu, s'il vous plaît ajouter constructeur par défaut pour chaque classe, il pourrait également être utiles.

9
répondu danny.lesnik 2011-10-02 10:40:19

Thumb Rule : Ajouter un constructeur par défaut pour chaque classe que vous avez utilisée comme classe de cartographie. Vous avez manqué ce et question!

Simplement ajouter un constructeur par défaut et cela devrait fonctionner.

9
répondu Badal 2015-01-19 06:52:25

vous devez créer le constructeur vide de mannequin dans notre classe de modèle.Ainsi, tout en cartographiant json, il a défini par la méthode setter.

5
répondu Suresh Patil 2017-05-03 12:11:29

si vous commencez à annoter constructeur, vous devez annoter tous les champs.

avis, Mon personnel.le champ name est associé à" ANOTHER_NAME " dans la chaîne JSON.

     String jsonInString="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}";
     ObjectMapper mapper = new ObjectMapper();
     Staff obj = mapper.readValue(jsonInString, Staff.class);
     // print to screen

     public static class Staff {
       public String name;
       public Integer age;
       public Staff() {         
       }        

       //@JsonCreator - don't need this
       public Staff(@JsonProperty("ANOTHER_NAME") String   n,@JsonProperty("age") Integer a) {
        name=n;age=a;
       }        
    }
4
répondu Vortex 2016-09-10 06:16:26

vous devez réaliser quelles options Jackson A disponibles pour la desérialisation. En Java, les noms d'arguments 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 objet 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 vide et les setters. S'il n'y a pas de setters, une magie noire (reflets) 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 générateur de modèle. Si vous rencontrez quelques exceptions, bonne chance. Le traitement des erreurs dans Jackson craint beaucoup, il est difficile de comprendre ce charabia dans les messages d'erreur.

2
répondu Vlasec 2018-08-09 17:07:19

à Défaut personnalisé jackson Sérialiseurs/Deserializers pourrait également être le problème. Bien que ce ne soit pas votre cas, il vaut la peine de mentionner.

j'ai fait face à la même exception et ce fut le cas.

0
répondu Artem Novikov 2016-01-13 23:03:38

pour moi, cela fonctionnait, mais la mise à niveau des bibliothèques a fait apparaître ce problème. Le problème était d'avoir une classe comme ceci:

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

utilisant lombok:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
</dependency>

retour à

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.10</version>
</dependency>

a réglé le problème. Je ne sais pas pourquoi, mais je voulais le documenter pour l'avenir.

0
répondu eis 2018-06-08 20:07:19

généralement cette erreur vient parce que nous ne faisons pas constructeur par défaut, mais dans mon cas, le problème venait seulement en raison de j'ai fait utilisé classe objet dans la classe parent. Cette a perdu toute ma journée.

0
répondu alok 2018-10-08 12:25:04