JSON-Verarbeitung in Java EE 7

1. Übersicht

In diesem Artikel erfahren Sie, wie Sie JSON nur mit Java EE verarbeiten, ohne Abhängigkeiten von Drittanbietern wie Jersey oder Jackson zu verwenden. So ziemlich alles, was wir verwenden, wird vom Paket javax.json bereitgestellt.

2. Schreiben eines Objekts in eine JSON- Zeichenfolge

Das Konvertieren eines Java-Objekts in einen JSON- String ist sehr einfach. Nehmen wir an, wir haben eine einfache Personenklasse :

public class Person { private String firstName; private String lastName; private Date birthdate; // getters and setters }

Um eine Instanz dieser Klasse in einen JSON- String zu konvertieren , müssen Sie zuerst eine Instanz von JsonObjectBuilder erstellen und Eigenschafts- / Wertepaare mit der Methode add () hinzufügen :

JsonObjectBuilder objectBuilder = Json.createObjectBuilder() .add("firstName", person.getFirstName()) .add("lastName", person.getLastName()) .add("birthdate", new SimpleDateFormat("DD/MM/YYYY") .format(person.getBirthdate()));

Beachten Sie, dass die add () -Methode einige überladene Versionen hat. Es kann die meisten primitiven Typen (sowie Boxobjekte) als zweiten Parameter empfangen.

Sobald wir die Eigenschaften festgelegt haben, müssen wir das Objekt nur noch in einen String schreiben :

JsonObject jsonObject = objectBuilder.build(); String jsonString; try(Writer writer = new StringWriter()) { Json.createWriter(writer).write(jsonObject); jsonString = writer.toString(); }

Und das ist es! Der generierte String sieht folgendermaßen aus:

{"firstName":"Michael","lastName":"Scott","birthdate":"06/15/1978"}

2.1. Verwenden von JsonArrayBuilder zum Erstellen von Arrays

Um unser Beispiel etwas komplexer zu gestalten, nehmen wir an, dass die Person- Klasse geändert wurde, um eine neue Eigenschaft namens E-Mails hinzuzufügen, die eine Liste von E-Mail-Adressen enthält:

public class Person { private String firstName; private String lastName; private Date birthdate; private List emails; // getters and setters }

Um alle Werte aus dieser Liste zum JsonObjectBuilder hinzuzufügen, benötigen wir die Hilfe von JsonArrayBuilder :

JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); for(String email : person.getEmails()) { arrayBuilder.add(email); } objectBuilder.add("emails", arrayBuilder);

Beachten Sie, dass wir eine weitere überladene Version der add () -Methode verwenden, die ein JsonArrayBuilder- Objekt als zweiten Parameter verwendet.

Schauen wir uns also den generierten String für ein Personenobjekt mit zwei E-Mail-Adressen an:

{"firstName":"Michael","lastName":"Scott","birthdate":"06/15/1978", "emails":["[email protected]","[email protected]"]}

2.2. Formatieren der Ausgabe mit PRETTY_PRINTING

Daher haben wir ein Java-Objekt erfolgreich in einen gültigen JSON- String konvertiert . Bevor wir zum nächsten Abschnitt übergehen, fügen wir einige einfache Formatierungen hinzu, um die Ausgabe „JSON-ähnlicher“ und leichter lesbar zu machen.

In den vorherigen Beispielen haben wir einen JsonWriter mit dem einfachen Json erstellt . statische Methode createWriter () . Um mehr Kontrolle über den generierten String zu erhalten , werden wir die JsonWriterFactory- Fähigkeit von Java 7 nutzen , um einen Writer mit einer bestimmten Konfiguration zu erstellen.

Map config = new HashMap(); config.put(JsonGenerator.PRETTY_PRINTING, true); JsonWriterFactory writerFactory = Json.createWriterFactory(config); String jsonString; try(Writer writer = new StringWriter()) { writerFactory.createWriter(writer).write(jsonObject); jsonString = writer.toString(); }

Der Code mag etwas ausführlich aussehen, aber er macht wirklich nicht viel.

Zunächst wird eine Instanz von JsonWriterFactory erstellt, die eine Konfigurationszuordnung an ihren Konstruktor übergibt . Die Karte enthält nur einen Eintrag, der die Eigenschaft PRETTY_PRINTING auf true setzt. Dann verwenden wir diese Factory-Instanz, um einen Writer zu erstellen, anstatt Json.createWriter () zu verwenden .

Die neue Ausgabe enthält die markanten Zeilenumbrüche und Tabellen, die einen JSON- String kennzeichnen :

{ "firstName":"Michael", "lastName":"Scott", "birthdate":"06/15/1978", "emails":[ "[email protected]", "[email protected]" ] }

3. Erstellen eines Java- Objekts aus einer Zeichenfolge

Führen Sie nun die umgekehrte Operation aus: Konvertieren Sie einen JSON- String in ein Java-Objekt.

Der Hauptteil des Konvertierungsprozesses dreht sich um JsonObject . Verwenden Sie zum Erstellen einer Instanz dieser Klasse die statische Methode Json.createReader (), gefolgt von readObject () :

JsonReader reader = Json.createReader(new StringReader(jsonString)); JsonObject jsonObject = reader.readObject();

Die Methode createReader () verwendet einen InputStream als Parameter. In diesem Beispiel verwenden wir einen StringReader, da unser JSON in einem String- Objekt enthalten ist. Dieselbe Methode kann jedoch auch zum Lesen von Inhalten aus einer Datei verwendet werden, z. B. mithilfe von FileInputStream .

Mit einer Instanz von JsonObject können wir die Eigenschaften mit der Methode getString () lesen und die erhaltenen Werte einer neu erstellten Instanz unserer Person- Klasse zuweisen :

Person person = new Person(); person.setFirstName(jsonObject.getString("firstName")); person.setLastName(jsonObject.getString("lastName")); person.setBirthdate(dateFormat.parse(jsonObject.getString("birthdate")));

3.1. Mit JsonArray Get Liste Werte

Wir müssen eine spezielle Klasse namens JsonArray verwenden , um Listenwerte aus JsonObject zu extrahieren :

JsonArray emailsJson = jsonObject.getJsonArray("emails"); List emails = new ArrayList(); for (JsonString j : emailsJson.getValuesAs(JsonString.class)) { emails.add(j.getString()); } person.setEmails(emails);

Das ist es! Wir haben eine vollständige Instanz von Person aus einem Json- String erstellt .

4. Abfragen nach Werten

Nehmen wir nun an, wir interessieren uns für ein ganz bestimmtes Datenelement, das in einem JSON- String liegt .

Betrachten Sie den folgenden JSON, der einen Kunden aus einer Zoohandlung darstellt. Nehmen wir an, Sie müssen aus irgendeinem Grund den Namen des dritten Haustieres aus der Liste der Haustiere abrufen:

{ "ownerName": "Robert", "pets": [{ "name": "Kitty", "type": "cat" }, { "name": "Rex", "type": "dog" }, { "name": "Jake", "type": "dog" }] }

Converting the whole text into a Java object just to get a single value wouldn't be very efficient. So, let's check a couple of strategies to query JSON Strings without having to go through the whole conversion ordeal.

4.1. Querying Using Object Model API

Querying for a property's value with a known location in the JSON structure is straightforward. We can use an instance of JsonObject, the same class used in previous examples:

JsonReader reader = Json.createReader(new StringReader(jsonString)); JsonObject jsonObject = reader.readObject(); String searchResult = jsonObject .getJsonArray("pets") .getJsonObject(2) .getString("name"); 

The catch here is to navigate through jsonObject properties using the correct sequence of get*() methods.

In this example, we first get a reference to the “pets” list using getJsonArray(), which returns a list with 3 records. Then, we use getJsonObject() method, which takes an index as a parameter, returning another JsonObject representing the third item in the list. Finally, we use getString() to get the string value we are looking for.

4.2. Querying Using Streaming API

Another way to perform precise queries on a JSON String is using the Streaming API, which has JsonParser as its main class.

JsonParser provides extremely fast, read-only, forward access to JS, with the drawback of being somewhat more complicated than the Object Model:

JsonParser jsonParser = Json.createParser(new StringReader(jsonString)); int count = 0; String result = null; while(jsonParser.hasNext()) { Event e = jsonParser.next(); if (e == Event.KEY_NAME) { if(jsonParser.getString().equals("name")) { jsonParser.next(); if(++count == 3) { result = jsonParser.getString(); break; } } } }

This example delivers the same result as the previous one. It returns the name from the third pet in the pets list.

Once a JsonParser is created using Json.createParser(), we need to use an iterator (hence the “forward access” nature of the JsonParser) to navigate through the JSON tokens until we get to the property (or properties) we are looking for.

Every time we step through the iterator we move to the next token of the JSON data. So we have to be careful to check if the current token has the expected type. This is done by checking the Event returned by the next() call.

There are many different types of tokens. In this example, we are interested in the KEY_NAME types, which represent the name of a property (e.g. “ownerName”, “pets”, “name”, “type”). Once we stepped through a KEY_NAME token with a value of “name” for the third time, we know that the next token will contain a string value representing the name of the third pet from the list.

This is definitely harder than using the Object Model API, especially for more complicated JSON structures. The choice between one or the other, as always, depends on the specific scenario you will be dealing with.

5. Conclusion

We have covered a lot of ground on the Java EE JSON Processing API with a couple of simple examples. To learn other cool stuff about JSON processing, check our series of Jackson articles.

Überprüfen Sie den Quellcode der in diesem Artikel verwendeten Klassen sowie einige Komponententests in unserem GitHub-Repository.