2016-06-21 4 views
7

Dies scheint, als sollte es ein ziemlich gelöstes/gut adressiertes Problem sein, aber ich finde nicht viele Hinweise darauf - in der Hoffnung, dass dies kein Betrogener ist.Deserialisieren von verschachtelten Objekten innerhalb der JSON-Antwort mit Jackson

Mein Szenario ist im Grunde, dass ich paginierte JSON Antworten bin raubend, die wie folgt aussehen:

{ 
    "objects": [...], 
    "meta": { 
    "total": 5000, 
    "page": 1, 
    "result_pages": 20, 
    "links": { 
     "prev": null, 
     "next": "/api/v3/objects/somequery?page=2" 
    } 
    } 
} 

Offensichtlich ist dies vereinfacht, aber hoffentlich wird es den Punkt herüber.

Alles, was mich wirklich interessiert, sind die Felder objects und next, aber es sieht so aus, als müsste ich eine ganze Hierarchie von DTOs erstellen, um die verschachtelten Felder erfolgreich zu deserialisieren.

Gibt es eine Jackson Annotation, die mich das alles überspringen lassen würde? Wenn nicht, gibt es dafür eine Reihe von Best Practices, bei denen es nicht um eine Vielzahl meist leerer Klassen und Dateien geht?

Antwort

8

Gibt es eine Jackson Annotation, die mich all das überspringen lassen würde?

Sie können JsonDeserialize verwenden und benutzerdefinierten JsonDeserializer definieren.

class MetaDeserializer extends JsonDeserializer<String> { 
    @Override 
    public String deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { 
     JsonNode tree = jp.readValueAsTree(); 
     return tree.get("links").get("next").asText(); 
    } 
} 

Hier verwendete ich einfache Karte Deserialisierung, aber wenn Sie möchten, können Sie Ihre eigene schnelle Deserialisierung implementieren.

Und das Objekt

class MetaObject { 
    public List<Integer> objects; 

    @JsonDeserialize(using = MetaDeserializer.class) 
    public String meta; 

    @Override 
    public String toString() { 
     return "MetaObject{" + "objects=" + objects + ", meta='" + meta + '\'' + '}'; 
    } 
} 

Und wenn Sie MetaObject result = mapper.readValue("...", MetaObject.class) aufrufen erhalten Sie, was Sie wollen

MetaObject{objects=[1, 2, 3], meta='/api/v3/objects/somequery?page=2'} 
+1

Wäre es vielleicht einfacher sein, nur die oben genannten verwenden 'JsonDeserializer' mit einer Anmerkung auf eine 'String next' -Eigenschaft und einfach so tun, es ist flach, auf der gleichen root-Ebene wie' "objects" '? –

+0

@ap, Sie können diese Anmerkung anders verwenden, auch an der Spitze der Klasse, hier die Dokumentation, https://fasterxml.github.io/jackson-databind/javadoc/2.3.0/com/fasterxml/jackson/databind /annotation/JsonDeserialize.html – SerCe

+1

Für zukünftige Bewerber sollte ich erwähnen, dass die obige Antwort die '.asText()' Methode verwendet, die anscheinend falsch ist. Ich habe nach einiger Arbeit '.textValue()' benutzt und es funktioniert wie ein Zauber. –

Verwandte Themen