Jersey: No se ha encontrado un constructor adecuado para el tipo [tipo simple, cosa de clase]: no se puede crear una instancia desde el objeto JSON


Tengo un recurso con un método como:

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/add")
public Response putThing(Thing thing) {
    try {
        //Do something with Thing object
        return Response.status(HttpStatus.SC_OK).build();
    } catch (Exception e) {
        log.error("Request failed", e);
        return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build();
    }
}

Cosa:

public class Thing {
    private final String symbol;
    private final String name;

    public Stock(String symbol, String name) {
        this.symbol = symbol;
        this.name = name;
    }

    public String getSymbol() {
        return this.symbol;
    }

    public String getName() {
        return this.name;
    }
}

Cuando hago una solicitud PUT como:

PUT /rest/add HTTP/1.1
Host: localhost:8135
Content-Type: application/json
Cache-Control: no-cache

{"symbol":"some symbol","name":"some name"}

Recibo la siguiente respuesta:

No se encontró ningún constructor adecuado para type [tipo simple, cosa de clase]: can no crear instancias desde el objeto JSON (falta el constructor predeterminado o creador, o tal vez necesita agregar / habilitar información de tipo?)

¿Por qué Jersey/Jackson no deserializa mi objeto JSON en mi POJO?

Author: Edd, 2015-06-28

2 answers

Necesita un constructor y setters no-arg, o use @JsonCreator. Lo más fácil de hacer sería simplemente agregar el no-arg con setters. Jackson necesita a los armadores cuando deserializa. Para la serialización, todo lo que se necesita son captadores.

EDITAR

Para mantenerlo inmutable, puede usar @JsonCreator en el constructor. Por ejemplo

@JsonCreator
public Thing(@JsonProperty("symbol") String symbol, 
             @JsonProperty("name") String name) {

    this.symbol = symbol;
    this.name = name;
}

Ver más Jackson Annotations: @JsonCreator demystified

 34
Author: Paul Samsotha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-27 23:20:42

No estoy absolutamente seguro, pero creo que esto es todo.

La forma en que Jackson quiere trabajar es esta: crea el objeto usando el constructor predeterminado (sin argumento). Luego utiliza setters para establecer cada una de las variables de instancia. Esto puede parecer el largo camino, pero es realmente la única manera, porque Jackson no puede ser lo suficientemente inteligente como para averiguar en qué orden pasar los parámetros del constructor. Así que su código tiene dos problemas principales (bueno, tres, pero voy a asumir que tu clase fue llamada Stock antes de que la limpiaras para publicarla; -)).
1. Necesitas un constructor sin argumento. Por lo que sé, Java proporciona un constructor predeterminado si no escribes uno, pero tan pronto como haces cualquier constructor, el constructor sin argumento predeterminado desaparece.
2. Necesita configuradores para sus variables de instancia (y hacerlos públicos no es suficiente, tienen que tener configuradores reales). Oh, parece que sus variables de instancia son finales, eso no va trabajar. Mi forma favorita de administrar todos los setters de copiar/pegar es usar una biblioteca llamada lombok. De todos modos, por ahora solo necesitas esos setters.

 3
Author: OrigamiMarie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-27 23:10:52