2015-06-27 9 views
21

Ich habe eine Ressource mit einem Verfahren wie:Jersey: Kein geeigneter Konstruktor für Typen [einfache Art, Klasse Thing] gefunden: kann nicht von JSON-Objekt instanziiert

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

Thing:

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

wenn ich eine PUT-Anfrage wie:

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

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

ich die folgende Antwort erhalten:

Kein passender Konstruktor für Typ [einfache Art, Klasse Thing] gefunden: kann nicht von JSON-Objekt instanziiert (Standardkonstruktors oder Schöpfer fehlt, oder vielleicht müssen Typinformationen hinzufügen/aktivieren?)

Warum wird das JSON-Objekt von Jersey/Jackson nicht in mein POJO deserialisiert?

+0

Mögliche Duplikate von [JsonMappingException: Es wurde kein geeigneter Konstruktor für den Typ \ gefunden [einfacher Typ, Klasse \]: kann nicht vom JSON-Objekt instanziiert werden] (https://stackoverflow.com/questions/7625783/jsonmappingexception-no-uitable- Konstruktor-gefunden-für-Typ-Simple-Type-Klasse) – Abhijeet

Antwort

31

Sie benötigen einen Konstruktor und Setter ohne Argumenten oder verwenden Sie @JsonCreator. Am einfachsten wäre es, das No-Arg mit Settors zu ergänzen. Jackson benötigt die Setter beim Deserialisieren. Für die Serialisierung sind nur Getter erforderlich.

EDIT

zu halten es unveränderlich, Sie @JsonCreator auf den Konstruktor verwenden können. Zum Beispiel

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

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

Weitere Jackson Annotations: @JsonCreator demystified

+0

Definitiv für die Unveränderbarkeit, ja. Alternativ glaube ich, dass Sichtbarkeit auf ANY auf dem ObjectMapper gesetzt werden könnte und es die privaten Felder behandelt. –

2

ich nicht unbedingt positiv bin, aber ich denke, das ist es.

Die Art, wie Jackson arbeiten möchte, ist dies: Er erstellt das Objekt mit dem Standardkonstruktor (kein Argument). Dann verwendet es Setter, um jede Instanzvariable zu setzen. Dies mag wie der lange Weg erscheinen, aber es ist wirklich der einzige Weg, denn Jackson kann nicht wirklich schlau genug sein, um herauszufinden, in welcher Reihenfolge die Konstruktorparameter übergeben werden. Ihr Code hat also zwei Hauptprobleme (naja, drei, aber Ich gehe davon aus, dass deine Klasse Stock genannt wurde, bevor du sie für das Posting aufgeräumt hast ;-)).
1. Sie benötigen einen Konstruktor ohne Argumente. Soweit ich weiß, stellt Java einen Standardkonstruktor zur Verfügung, wenn Sie keinen schreiben, aber sobald Sie einen Konstruktor erstellen, verschwindet der Standardkonstruktor für keine Argumente.
2. Sie benötigen Setter für Ihre Instanzvariablen (und sie öffentlich zu machen ist nicht gut genug, sie müssen tatsächliche Setter haben). Oh, es sieht so aus, als ob deine Instanzvariablen endgültig sind, das wird nicht funktionieren. Meine bevorzugte Methode zum Verwalten aller kopierten/eingefügten Setter ist die Verwendung einer Bibliothek namens lombok. Wie auch immer, für den Moment brauchen Sie nur diese Setter.