Recibo el siguiente error cuando intento obtener una solicitud JSON y procesarla:
org.codehaus.jackson.map.JsonMappingException: No se encontró 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 de tipo?)
Aquí está el JSON que estoy tratando de 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 una envoltura de ApplesDO:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
Manzanas DO:
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. Ayude con los parámetros de configuración para que Jackson convierta JSON en objetos Java. Estoy usando Spring Framework.
EDITAR: Incluyó el error principal que está causando este problema en la clase de muestra anterior. Busque la respuesta aceptada para la solución.
Respuestas:
Entonces, finalmente me di cuenta de cuál es el problema. No es un problema de configuración de Jackson como dudé.
En realidad, el problema estaba en la clase ApplesDO :
Había un constructor personalizado definido para la clase que lo convertía en el constructor predeterminado. La introducción de un constructor ficticio ha hecho que el error desaparezca:
fuente
Esto sucede por estos motivos:
su clase interna debe definirse como estática
Es posible que no tenga un constructor predeterminado en su clase ( ACTUALIZACIÓN: este no parece ser el caso)
Podría ser que sus Setters no estén definidos correctamente o no sean visibles (por ejemplo, setter privado)
fuente
Me gustaría agregar otra solución a esto que no requiera un constructor ficticio. Dado que los constructores ficticios son un poco desordenados y posteriormente confusos. Podemos proporcionar un constructor seguro y al anotar los argumentos del constructor permitimos que jackson determine la asignación entre el parámetro del constructor y el campo.
así que lo siguiente también funcionará. Tenga en cuenta que la cadena dentro de la anotación debe coincidir con el nombre del campo.
fuente
@JsonCreator
el constructor con@JsonProperty
.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) requirió una instancia de la clase de cierre, que no estaba disponible para Jackson.
En este caso, mover la clase interna a su propio archivo .java solucionó el problema.
fuente
En general, este error se produce porque no hacemos un constructor predeterminado, pero en mi caso, el problema se produjo solo porque hice una clase de objeto utilizada dentro de la clase principal. Esto ha desperdiciado todo mi día.
fuente
static
.Regla general : agregue un constructor predeterminado para cada clase que utilizó como clase de mapeo. Te perdiste esto y surgió el problema!
Simplemente agregue el constructor predeterminado y debería funcionar.
fuente
¿Puedes por favor probar esta estructura? Si recuerdo correcto, puedes usarlo de esta manera:
En segundo lugar, agregue el constructor predeterminado a cada clase que también podría ayudar.
fuente
Debe crear un constructor vacío ficticio en nuestra clase de modelo, por lo tanto, al mapear json, se establece mediante el método setter.
fuente
Si comienza a anotar un constructor, debe anotar todos los campos.
Observe que mi campo Staff.name está asignado a "ANOTHER_NAME" en la cadena JSON.
fuente
Debe darse cuenta de las opciones que Jackson tiene disponibles para la deserialización. En Java, los nombres de argumentos de método no están presentes en el código compilado. 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 setters vacíos. Si no hay setters, se usa algo de magia oscura (reflejos) para hacerlo.
Si desea usar un constructor con Jackson, debe usar las anotaciones mencionadas por @PiersyP en su respuesta. También puede usar un patrón de construcción. 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.
fuente
Con respecto a la última publicación, tuve el mismo problema cuando el uso de Lombok 1.18. * Generó el problema.
Mi solución fue agregar @NoArgsConstructor (constructor sin parámetros), ya que @Data incluye por defecto @RequiredArgsConstructor (Constructor con parámetros).
Documentación de lombok https://projectlombok.org/features/all
Eso resolvería el problema:
fuente
Serializadores / deserializadores jackson personalizados también podrían ser el problema. Aunque no es su caso, vale la pena mencionarlo.
Me enfrenté a la misma excepción y ese fue el caso.
fuente
Para mí, esto solía funcionar, pero la actualización de las bibliotecas hizo que apareciera este problema. El problema era tener una clase como esta:
Usando lombok:
Volviendo a
Solucionado el problema. No estoy seguro de por qué, pero quería documentarlo para el futuro.
fuente