web-dev-qa-db-fra.com

Jersey: Aucun constructeur approprié trouvé pour le type [type simple, classe Thing]: ne peut pas instancier à partir d'un objet JSON

J'ai une ressource avec une méthode comme:

@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();
    }
}

Chose:

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

Quand je fais une demande PUT comme:

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

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

J'obtiens la réponse suivante:

Aucun constructeur approprié trouvé pour le type [type simple, classe Thing]: ne peut pas instancier à partir de l'objet JSON (constructeur ou créateur par défaut manquant, ou peut-être besoin d'ajouter/activer les informations de type?)

Pourquoi Jersey/Jackson ne désérialise-t-il pas mon objet JSON dans mon POJO?

25
Edd

Vous avez besoin d'un constructeur et de setters sans argument, ou utilisez @JsonCreator. La chose la plus simple à faire serait simplement d'ajouter le no-arg avec les setters. Jackson a besoin des poseurs lors de la désérialisation. Pour la sérialisation, il suffit d'avoir des getters.

[~ # ~] modifier [~ # ~]

Pour le conserver immuable, vous pouvez utiliser @JsonCreator sur le constructeur. Par exemple

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

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

Voir plus Annotations Jackson: @JsonCreator démystifié

37
Paul Samsotha

Je ne suis pas absolument positif, mais je pense que c'est ça.

La façon dont Jackson veut travailler est la suivante: il crée l'objet en utilisant le constructeur par défaut (sans argument). Ensuite, il utilise des setters pour définir chacune des variables d'instance. Cela peut sembler long, mais c'est vraiment le seul moyen, car Jackson ne peut pas vraiment être assez intelligent pour comprendre dans quel ordre passer les paramètres du constructeur. Votre code a donc deux problèmes principaux (enfin, trois, mais Je vais supposer que votre classe s'appelait Stock avant que vous ne la nettoyiez pour la publication ;-)).
1. Vous avez besoin d'un constructeur sans argument. D'après ce que je sais, Java fournit un constructeur par défaut si vous n'en écrivez pas, mais dès que vous créez un constructeur, le constructeur sans argument par défaut disparaît.
2. Vous avez besoin de setters pour vos variables d'instance (et les rendre publics ne suffit pas, ils doivent avoir de vrais setters). Oh, il semble que vos variables d'instance soient finales, cela ne fonctionnera pas. Ma façon préférée de gérer tous les setters copiés/collés est d'utiliser une bibliothèque appelée lombok. Quoi qu'il en soit, pour l'instant, vous avez juste besoin de ces setters.

3
OrigamiMarie