2012-12-10 3 views
7

Ich schreibe einen REST-Dienst mit Jersey. Ich habe eine abstrakte Klasse Promotion, die eine Anmerkung hat:@JsonTypeInfo (verwenden = JsonTypeInfo.Id.CLASS) funktioniert nicht, wenn Antwort zurückgegeben wird

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 

Dank, dass, wenn ich eine Liste von Objekten zurück:

@GET 
@Produces(MediaType.APPLICATION_JSON) 
@Path("promotions/") 
public List<Promotion> getClosestPromotions() { 
List<Promotion> promotions = getPromotions(); //here I get some objects 

return promotions; 
} 

ich eine JSON-String mit einem „@ Klasse“ -Feld erhalten für jedes Objekt in dieser Liste. Aber das Problem ist, dass, wenn ich wieder eine Antwort:

@GET 
@Produces(MediaType.APPLICATION_JSON) 
@Path("promotions/") 
public Response getClosestPromotions() { 
List<Promotion> promotions = getPromotions(); //here I get some objects 

return Response.ok().entity(promotions).build(); 
} 

Ich bin fast die gleiche Liste bekommen, aber ohne zusätzliche „@class“ ein. Warum ist das und was kann ich tun, um eine Liste mit "@class" -Feld zu erhalten, die eine Liste in Response zurückgibt? Und übrigens, überraschend, es funktioniert, wenn ich eine Antwort mit einem Promotion-Objekt nur als eine Entität zurückgegeben und ich bekomme dieses "@class" -Feld.

+1

Ich habe nicht genug für eine Antwort noch nicht, aber mit Jersey Jackson Standard Serializer mit dem zusätzlichen Metadaten. Die Entitätsmethode akzeptiert ein Objekt. Der zugrunde liegende Code prüft den Typ wahrscheinlich zur Laufzeit, um die Typinformationen wiederherzustellen. Leider wird es so weit gehen wie Liste und nicht Liste . Es schreibt es als eine Liste ohne generische Typinformationen, daher würden Sie das Klassenfeld verlieren. Das Schreiben eines Objekts, das die Liste als eine Mitgliedsvariable enthält, wird wahrscheinlich funktionieren, aber ich versuche, etwas saubereres zu finden. –

Antwort

5

Vielleicht würden Sie versuchen:

GenericEntity<Collection<Promotion>> genericEntity = 
      new GenericEntity<Collection<Promotion>>(promotions){}; 
return Response.ok().entity(genericEntity).build(); 
+1

Vielen Dank! Ich habe es endlich funktioniert! – krajol

+1

Dies ist eine einfache Lösung, die sehr gut funktioniert, danke fürs Teilen! Der einzige Nachteil ist, dass wir daran denken müssen, unsere Kollektionen immer auf diese Weise zu verpacken. –

2

Versuchen Sie, die Untertypen Anmerkung hinzufügen, hier ist ein Beispiel, das ich verwende. Dies kann Ihr Problem lösen, indem Sie alle funktionsfähigen Untertypen angeben. Sorry hat dein exaktes Beispiel nicht getestet.

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value=MetricCollection.class), 
    @JsonSubTypes.Type(value=Column.class), 
    @JsonSubTypes.Type(value=IntegerColumn.class), 
    @JsonSubTypes.Type(value=DoubleColumn.class), 
    @JsonSubTypes.Type(value=StringColumn.class) 
}) 
public interface IMetricCollection<T extends IMetric> { 
... 
} 
0

Wenn Sie JAXB verwendet, um Ihre Klassen zu generieren, können Sie sicherlich so etwas wie @XmlElements mit verschiedenen Typen haben eine Liste zu analysieren.

Wenn Sie nun die gleichen JAXB-Klassen mit Jersey/Jackson verwenden, können Sie die Metadaten der Klasse erweitern, indem Sie @JsonTypeInfo und @JsonSubTypes hinzufügen, um zu beschreiben, wie der Name der Liste/Anordnung von Objekten formatiert wird.

Während @JsonTypeInfo den hinzuzufügenden Typ beschreibt, gibt @JsonSubTypes die Optionen der eingeschlossenen Auflistung an. Zum Beispiel, As.PROPERTY, um eine Eigenschaft der Ausgabe zu definieren, wie im folgenden Beispiel angezeigt, wo eine Liste von Entitäten, die Elemente unterschiedlicher Typen haben können, einschließlich des Typs selbst ("Form") zusätzlich zu 2 anderen Typen " Feld "und" Tabelle ".

public class Form { 

    @XmlElements({ 
    @XmlElement(name = "field", type = Field.class), 
    @XmlElement(name = "form", type = Form.class), 
    @XmlElement(name = "table", type = Table.class) 
    }) 
    @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "obj") 
    @JsonSubTypes({ 
    @JsonSubTypes.Type(value = Field.class), 
    @JsonSubTypes.Type(value = Form.class), 
    @JsonSubTypes.Type(value = Table.class) 
    }) 
    @Generated(value = "com.sun.tools.internal.xjc.Driver", date = "2013-11-11T02:08:36-08:00", comments = "JAXB RI v2.2.4-2") 
    @JsonProperty("entities") 
    protected List<Object> fieldOrFormOrTable; 

Die Serialisierung des Objekts die folgenden ... wird sein

 "entities": [ 
        { 
        "obj": "Table", 
        "row": { 
         "id": 1, 
         "fields": [ 
          { 
           "id": "DEBUGARY", 
           "type": "Text", 
           "kind": "user" 
          } 
         ] 
        }, 
        "id": "DBGARRAY" 
       }, 
       { 
        "obj": "field", 
        "id": "IDBG", 
        "type": "Text", 
        "kind": "user" 
       }, 
     ..., ..., ...] 
Verwandte Themen