2013-05-10 10 views
10

eine Runde auf dem Zoo am Beispiel:Jackson Polymorphe Deserialisierung - Können Sie die Existenz eines Feldes anstelle eines bestimmten Wertes verlangen?

public class ZooPen { 
    public String type; 
    public List<Animal> animals; 
} 

public class Animal { 
    public String name; 
    public int age; 
} 

public class Bird extends Animal { 
    public double wingspan; 
} 

I Tier Instanzen polymorphe Deserialisierung zu konstruieren, verwenden, wenn keine Spannweite angegeben ist, und Vogel-Instanzen, wenn es ist. In Jackson, sieht nicht typisierten Deserialisierung der Regel etwas wie folgt aus:

@JsonTypeInfo( 
    use = JsonTypeInfo.Id.NAME, 
    include = JsonTypeInfo.As.PROPERTY, 
    property = "wingspan", 
    visible = true, 
    defaultImpl = Animal.class 
) 
@JsonSubTypes({ 
    @Type(value = Bird.class, name = **???**) 
}) 
public class Animal { 
    ... 
} 

Die Spannweite Wert kann alles sein, und ohne dass passende etwas spezifisch, Jackson fällt zurück auf die defaultImpl Klasse.

ich wahrscheinlich @JsonCreator

@JsonCreator 
public static Animal create(Map<String,Object> jsonMap) 
     throws JsonProcessingException { 

    ObjectMapper mapper = new ObjectMapper(); 
    if (jsonMap.get("wingspan") == null) { 
     // Construct and return animal 
    } else { 
     // Construct and return bird 
    } 
} 

Allerdings nutzen könnte, dann habe ich manuell, um zusätzliche Werte verarbeiten und konsistente Ausnahmen auslösen, und es ist nicht klar, ob das Tier richtig später serialisiert werden würde.

Gibt es eine Möglichkeit zu tun, was ich mit polymorpher Art Handhabung will? Es scheint, dass ich meinen eigenen TypeResolver oder TypeIdResolver verwenden kann, aber das scheint mehr Arbeit zu sein, als nur das Roh-JSer zu deserialisieren. Alternativ dazu gibt es möglicherweise eine Möglichkeit, den Zoomparentyp zu targetieren, obwohl er sich im übergeordneten Objekt befindet. Irgendwelche Ideen?

Edit:
TypeResolver und TypeIdResolver scheint untrennbar davon ausgehen, dass Typ info serialisiert, so die sind nicht gut zu bedienen. Wäre es möglich, meinen eigenen JsonDeserializer zu implementieren, der sich in den Lebenszyklus einklinkt, um den Typ anzugeben, aber dennoch grundlegende Verarbeitungsfunktionen für Jackson-Annotations verwendet? Ich habe mir JsonDeserializer.deserializeWithType(...) angesehen, aber das scheint die Deserialisierung vollständig an einen TypeDeserializer zu delegieren. Es gibt auch das Problem, dass ich einige der Objekte deserialisieren muss, bevor ich den zu verwendenden Typ kenne.

+3

Haben Sie jemals einen Weg gefunden, dies zu erreichen? Ich habe ein ähnliches Problem, aber mit mehreren "Bird" -ähnlichen Unterklassen, jedes mit einem bestimmten Feld, dessen Anwesenheit diese Unterklasse identifiziert. –

Antwort

0

Wenn Sie nicht mit Jackson verheiratet sind, glaube ich, dass etwas ähnliches mit FlexJSON erreicht werden kann.

http://flexjson.sourceforge.net/javadoc/flexjson/JSONDeserializer.html

Ich bin nicht vertraut mit Jackson Methoden für ähnliche Dinge zu tun, aber ich kann sagen, dass FlexJSON sehr performant ist, und im allgemeinen intuitiv während der Serialisierung/deserialziation Schritte zu verwenden.

Verwandte Themen