parsear para objeto libreria leer crear convertir con java json spring annotations jackson

java - libreria - JsonMappingException: no se encontrĂ³ un constructor adecuado para el tipo[tipo simple, clase]: no se puede crear una instancia del objeto JSON



libreria json para java (12)

¿Puedes por favor probar esta estructura? Si recuerdo bien puedes 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.

Recibo el siguiente error al intentar 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 (¿es necesario 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 el siguiente método de firma:

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

AllApplesDO es un envoltorio 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:

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. Por favor, ayuda 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. Por favor, busque la respuesta aceptada.


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

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


Debe crear un constructor vacío ficticio en nuestra clase de modelo. Por lo tanto, al asignar json, se establece mediante el método de establecimiento.


Debe darse cuenta de las opciones que Jackson tiene disponibles para la deserialización. En Java, los nombres de los argumentos de los métodos 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 ya configurado.

Por lo tanto, si hay un constructor vacío y también hay establecedores, utiliza el constructor y los definidores vacíos. Si no hay colocadores, se utiliza algo de magia oscura (reflexiones) 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 construcción. Si encuentras algunas excepciones, buena suerte. El manejo de errores en Jackson apesta a la perfección, es difícil entender que no haya errores en los mensajes de error.


En general, este error se produce porque no creamos el constructor predeterminado, pero en mi caso, el problema se produjo solo porque he creado una clase de objeto usado dentro de la clase principal. Esto ha desperdiciado todo mi día.


Entonces, finalmente me di cuenta de cuál es el problema. No es un problema de configuración de Jackson como 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 } }

Hubo un constructor personalizado definido para la clase que lo convierte en el constructor predeterminado. La introducción de un constructor ficticio ha cometido el error de desaparecer:

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. Tu clase interna debe definirse como estática

    private static class Condition { //jackson specific }

  2. Puede ser que no haya 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. Es posible que sus Setters no estén definidos correctamente o no sean visibles (por ejemplo, Setter privado)


Fallar los serializadores / deserializadores jackson personalizados también podría ser el problema. Aunque no es tu caso, vale la pena mencionarlo.

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


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 y el campo del constructor.

por lo que 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) { } }


Para mí, esto solía funcionar, pero la actualización de las bibliotecas hacía que apareciera este problema. El problema era 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; }

Utilizando lombok:

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

Cayendo de nuevo a

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

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


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

Observe que mi campo Staff.name se asigna 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; } }


Regla del pulgar : agregue un constructor predeterminado para cada clase que usó como clase de mapeo. Te perdiste esto y surgió el problema!
Simplemente agrega el constructor por defecto y debería funcionar.