JsonMappingException: No se ha encontrado un constructor adecuado para el tipo : no se puede crear una instancia del objeto JSON

Recibo el siguiente error al intentar obtener una solicitud JSON y procesarla:

org.codehaus.jackson.map.JsonMappingException: No se ha encontrado un constructor adecuado para el tipo [tipo simple, clase com.myweb.ApplesDO]: no se puede crear una instancia del objeto JSON (¿necesita agregar / habilitar información tipo?)

Aquí está el JSON que bash enviar:

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

En Controller, tengo la siguiente firma de método:

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

AllApplesDO es un contenedor de ApplesDO:

 public class AllApplesDO { private List applesDO; public List getApplesDO() { return applesDO; } public void setApplesDO(List 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 } } 

Creo que Jackson no puede convertir JSON en objetos Java para subclases. Ayuda con los parámetros de configuración para que Jackson convierta JSON en objetos Java. Estoy usando Spring Framework.

EDITAR: Se incluyó el error principal que está causando este problema en la clase de muestra anterior. Consulte la respuesta aceptada para la solución.

Entonces, finalmente me di cuenta cuál es el problema. No es un problema de configuración de Jackson, como lo dudaba.

En realidad, el problema estaba en la clase ApplesDO :

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

Había un constructor personalizado definido para la clase que lo convertía en el constructor predeterminado. La presentación de un constructor simulado ha hecho que el error desaparezca:

 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() { } } 

Esto sucede por estas razones:

  1. su clase interna debe definirse como estática

     private static class Condition { //jackson specific } 
  2. Puede ser que no tenga un constructor predeterminado en su clase ( ACTUALIZACIÓN: parece que este no es el caso)

     private static class Condition { private Long id; public Condition() { } // Setters and Getters } 
  3. Puede ser que tus Setters no estén definidos correctamente o no sean visibles (por ejemplo, setter privado)

Me gustaría agregar otra solución a esto que no requiera un constructor ficticio. Dado que los constructores simulados son un poco desordenados y, a continuación, confusos. Podemos proporcionar un constructor seguro y anotando los argumentos del constructor permitimos que jackson determine la correspondencia entre el parámetro del constructor y el campo.

entonces lo siguiente también funcionará. Tenga en cuenta que la cadena dentro de la anotación debe coincidir con el nombre del campo.

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

Cuando me encontré con este problema, fue el resultado de intentar usar una clase interna para servir como DO. La construcción de la clase interna (silenciosamente) requería una instancia de la clase envolvente, que no estaba disponible para Jackson.

En este caso, mover la clase interna a su propio archivo .java solucionó el problema.

¿Puedes por favor probar esta estructura? Si recuerdo correcto, puede usarlo de esta manera:

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

En segundo lugar, agregue el constructor predeterminado a cada clase, también podría ayudar.

Regla de pulgar : agrega un constructor predeterminado para cada clase que utilizaste como una clase de mapeo. ¡Te perdiste esto y surge el problema!
Simplemente agrega el constructor predeterminado y debería funcionar.

Tienes que crear un constructor vacío ficticio en nuestra clase de modelo. Así que al mapear json, se establece mediante el método setter.

Si comienza a anotar el constructor, debe anotar todos los campos.

Aviso, mi campo Staff.name está mapeado a “ANOTHER_NAME” en la cadena 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; } } 

Debes darte cuenta de las opciones que Jackson tiene disponibles para la deserialización. En Java, los nombres de argumento de método no están presentes en el código comstackdo. Es por eso que Jackson generalmente no puede usar constructores para crear un objeto bien definido con todo lo que ya está configurado.

Entonces, si hay un constructor vacío y también hay setters, usa el constructor y los setters vacíos. Si no hay establecedores, se usa algo de magia oscura (reflections) para hacerlo.

Si desea usar un constructor con Jackson, debe usar las anotaciones mencionadas por @PiersyP en su respuesta. También puedes usar un patrón de constructor. Si encuentra algunas excepciones, buena suerte. El manejo de errores en Jackson apesta a lo grande, es difícil entender ese galimatías en los mensajes de error.

Los Serializadores / Deserializadores personalizados fallidos también podrían ser el problema. Aunque no es tu caso, vale la pena mencionarlo.

Me enfrenté a la misma excepción y ese fue el caso.

Para mí, esto solía funcionar, pero la actualización de las bibliotecas hacía que apareciera este problema. El problema fue tener una clase como esta:

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

Usando lombok:

  org.projectlombok lombok 1.18.0  

Volviendo a

  org.projectlombok lombok 1.16.10  

Solucionado el problema. No estoy seguro por qué, pero quería documentarlo para el futuro.