GEDOPLAN
Jakarta EE (Java EE)

JPA + Rest, JSON-B in Action

Jakarta EE (Java EE)

“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!

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

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

Kurse

weitere Blogbeiträge

road 368719 640
Jakarta EE (Java EE)

Startup-Event in CDI 4

Während Plattformen wie Quarkus einen proprietären Event feuern, wenn einen Anwendung gestartet ist, kannte der Standard Jakarta EE dies bislang…

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!