GEDOPLAN

JPA + Rest, JSON-B in Action

Alle

„JSR 367“ alias JSON-B soll es endlich richten: ein standardisiertes JSON-Binding, ähnlich der Verarbeitung von XML mit JAXB. Gerade bei der Arbeit mit Rest-Schnittstellen und JPA stolpert man immer wieder über die gleichen Probleme. Wir machen einen ganz kurzen Rundflug über JSON-B und schauen uns eine Möglichkeit die JSON-B Adapters zu verwenden um JPA-Relationen zu mappen.

Einfache Möglichkeiten in die JSON-Generierung ein zu greifen fehlten bisher im Standard. Anbieter wie z.B. Jackson waren hier bereit viel weiter. JSON-B, Standard JSON-Binding in Java EE 8, bringt nun einige Möglichkeiten in diesem Bereich mit.

Annotationen

  • @JsonbProperty, Überschreiben des JSON-Property
  • @JsonbTransient, Attribute ignorieren
  • @JsonbPropertyOrder, Sortierung der Attribute anpassen
  • @JsonbDateFormat, Format für Datum
  • @JsonbNumberFormat, Format für Zahlen

Adapter

Neben der Implementierung einer Low-Level Serialisierung (implements JsonbSerializer) gibt es die Möglichkeit einen Art Converter zu implementieren der für die Verarbeitung einzelner Attribute verwendet werden kann. Ein interessantes Szenario für diesen Fall ist z.B. Entitäten die per JPA-Relationen referenziert werden nur durch ihre IDs zu repräsentieren (anstatt durch das gesamte Objekt). Das minimiert nicht nur die zu übertragenden Daten sondern verhindert auch das Problem von „circular dependencies“ bei bidirektionalen Relationen. Ein solcher (generischer) Adapter könnte so aussehen:

public abstract class EntityAdapter<T extends JPAEntity> implements JsonbAdapter<List<T>, JsonArray>{

    @Inject
    private EntityManager em;

    private Class getTargetClass() {
        return (Class) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public JsonArray adaptToJson(List orgnl) throws Exception {
        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
        orgnl.stream().map(JPAEntity::getId).forEach(arrayBuilder::add);
        return arrayBuilder.build();
    }

    public List adaptFromJson(JsonArray adptd) throws Exception {
        List list = new ArrayList();

        adptd.stream().forEach(val -> {
            Integer id = ((JsonNumber) val).intValue();
            list.add(em.getReference(getTargetClass(), id));
        });

        return list;
    }

}

Das Vorgehen ist schnell erklärt. Die Liste der referenzierten Entitäten wird nur mit den IDs befüllt. Diese werden bei der Deserialisierung dazu verwendet JPA-Referenzen zu laden um die korrekten Relationen wieder her zu stellen.

jsonb_demo.png

Dieser Adpater kann nun in unserer Resource verwendet werden um die JSON-B Konfiguration zu erweitern

    @GET
    public Response getTalks() {
        JsonbConfig config = new JsonbConfig().withAdapters(new EntityAdapter() {});
        Jsonb jsonb = JsonbBuilder.create(config);

        List allTalks = this.talkRepository.findAll();
        return Response.ok(jsonb.toJson(allTalks)).build();
    }

(zu beachten ist die Verwendung der anonymen Klasse bei der Instanziierung des Adapters. Dies wird benötigt damit JSON-B den generischen Typ zur Laufzeit ermitteln zu kann)

Alternativ ließe sich ein Adapter auch fest per Annotation an der Relation definieren:

@JsonbTypeAdapter(SpeakerAdapter.class)

(stand heute gibt es hier jedoch keine Möglichkeit zusätzliche Parameter, wie den Ziel-Entity-Typ mit zu geben (im Beispiel oben durch Generics und Reflection gelöst). Demzufolge müsste hier ein konkreter Adapter pro Entity Klasse implementiert werden)

Keine Frage viele Bibliotheken zur JSON-Verarbeitung sind ein ganzes Stück weiter. Mit JSON-B geht Java EE 8 aber einen großen Schritt in die richtige Richtung.

Github? Klar!

 

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Schulungen mit der selben Kategorie:

Blogkategorie: Alle
Es wurden keine Ergebnisse gefunden.

weitere Artikel

Kontakt

Brauchen Sie eine individuelle IT-Schulung, eine fundierte Beratung oder eine individuelle Softwareentwicklung? Dann sind Sie hier genau richtig!

Tim Neumann

Geschäftsleitung

GEDOPLAN GmbH
Stieghorster Straße 60
33605 Bielefeld

GEDOPLAN GmbH
Kantstraße 164
10623 Berlin

    Kontakt

    Tim Neumann

    Geschäftsleitung

    GEDOPLAN GmbH
    Stieghorster Straße 60
    33605 Bielefeld

    GEDOPLAN GmbH
    Kantstraße 164
    10623 Berlin

    Brauchen Sie eine individuelle IT-Schulung, eine fundierte Beratung oder eine individuelle Softwareentwicklung? Dann sind Sie hier genau richtig!