---
title: 'JSON-Serialisierung mit JSR 353/374 und JSR 367'
url: 'https://tutego.de/blog/javainsel/2018/07/json-serialisierung-mit-jsr-353-374-und-jsr-367'
markdown: 'https://tutego.de/blog/javainsel/2018/07/json-serialisierung-mit-jsr-353-374-und-jsr-367.md'
date: '2018-07-15'
description: 'Im Internet hat JSON das XML-Format zwecks Objektübertragung zwischen Server und Browser fast vollständig verdrängt. Das liegt daran, dass ein Browser JSON-Strings direkt in JavaScript-Objekte konvertieren kann, XML-Dokumente aber erst aufwändiger verarbeitet werden müssen. Neben dem Einsatzgebiet …'
taxonomy:
  category:
    - Insel
---

# JSON-Serialisierung mit JSR 353/374 und JSR 367

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://tutego.de/blog/javainsel/)

## JSON-Serialisierung mit JSR 353/374 und JSR 367

15.07.2018 · [Christian Ullenboom](https://tutego.de/blog/javainsel/author/admin/)

Im Internet hat JSON das XML-Format zwecks Objektübertragung zwischen Server und Browser fast vollständig verdrängt. Das liegt daran, dass ein Browser JSON-Strings direkt in JavaScript-Objekte konvertieren kann, XML-Dokumente aber erst aufwändiger verarbeitet werden müssen.

Neben dem Einsatzgebiet im Internet bietet JSON auch ein kompaktes Format, um etwa lokale Konfigurationsdateien zu kodieren.

### JSON im Kontext von JavaScript

Nehmen wir folgende Zeile JavaScript-Code, die ein Person-Objekt mit zwei Properties für Name und Alter definiert. Eine Property wird über ein Schlüssel-Wert-Paar beschrieben:

```java
var person = { "name" : "Michael Jackson", "age" : 50 };
```

Die Definition eines Objekts geschieht in der JSON (JavaScript `Object` Notation). Als Datentypen unterstützt JSON Zahlen, Wahrheitswerte, Strings, `Arrays`, `null` und Objekte – wie unser Beispiel zeigt. Die Deklarationen können geschachtelt sein, um Unterobjekte aufzubauen.

Zum Zugriff auf die JSON-Daten kommt der Punkt zum Einsatz, sodass der Name nach der Auswertung durch person.name zugänglich ist.

Eine Personenbeschreibung wie diese kann in einem `String` stehen, der von JavaScript zur Laufzeit ausgewertet wird.

```java
var json = 'person = { "name" : "Michael Jackson", "age" : 50 };';
```

Der Zugriff auf person.name liefert wie vorher den Namen, denn nach der Auswertung mit `eval(…)` wird JavaScript ein neues Objekt mit person im Kontext anlegen.

JSON ist besonders praktisch, wenn es darum geht, Daten zwischen einem Server und einem Browser mit JavaScript-Interpreter auszutauschen. Denn wenn der `String` json nicht von Hand mit einem `String` initialisiert wurde, sondern ein Server die Zeichenkette person = { … }; liefert, haben wir das, was heutzutage in modernen Ajax-Webanwendungen passiert.

Die letzte Frage ist nun, wie elegant der Server Zeichenketten im Datenaustauschformat JSON erzeugt und so Objekte überträgt. Den `String` per Hand aufzubauen ist eine Lösung, aber es geht besser.

### JSON-Verarbeitung mit der Java API for JSON Processing

Zum Verarbeiten von JSON-Dokumenten gibt es in der Java SE keine Standardklassen, sodass sich eine Reihe von Open-Source-Bibliotheken herausgeprägt haben; Jackson (<http://tutego.de/go/jackson>) gehört zu den populärsten Lösungen. 2013 wurde dann die JSR 353, »Java API for JSON Processing«, verabschiedet, die Teil der Jakarta EE 7 ist, 2014 dann das JSR 374 »Java API for JSON Processing 1.1«.

Wir können die JSON-API in unseren Java SE-Programmen nutzen, müssen dafür aber Java-Archive im Klassenpfad einbinden. Die Referenzimplementierung befindet sich unter <https://javaee.github.io/jsonp/>. Am einfachsten haben es Maven-Nutzer, sie binden in ihre POM die Abhängigkeiten auf den „Default provider for JSR 374:Java API for Processing JSON“ ein:

```
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1</version>
</dependency>
```

Die Implementierung hat eine Abhängigkeit zur JSON-API `javax.json:javax.json-api`, die wir dann nicht unbedingt selbst in die POM mit aufnehmen müssen.

#### Aufbau von JSON-Objekten, Formatieren und Parsen

Der Typ JsonObject ist in der API zentral, denn er definiert ein hierarchisches Model mit den Schlüssel-Wert-Paaren eines JSON-Objekts. Um ein JsonObject aufzubauen, können wir über den JsonObjectBuilder gehen, oder wir lassen den Parser JsonReader aus einer `String`-Repräsentation ein JsonObject erzeugen. Zum formatierten Schreiben in einen Ausgabestrom können wir einen einfachen JsonWriter von der Json-Klasse holen – es geht aber noch einfacher über `toString()` – oder über die JsonWriterFactory arbeiten, falls wir eine hübsche eingerückte Ausgabe wünschen. Ein Beispiel:

```java
Point p = new Point( 10, 20 );
```

JsonObjectBuilder `objBuilder` = `Json.createObjectBuilder()`.add( „x“, p.x )

```java
.add( "y", p.y );
JsonObject jsonObj = objBuilder.build();

System.out.println( jsonObj ); // {"x":10,"y":20}

Json.createWriter( System.out ).write( jsonObj ); // {"x":10,"y":20}

Map<String, Boolean> config = new HashMap<>();
config.put( JsonGenerator.PRETTY_PRINTING, true );
JsonWriterFactory writerFactory = Json.createWriterFactory( config );

StringWriter out = new StringWriter();
writerFactory.createWriter( out ).write( jsonObj );
System.out.println( out ); // {\\n "x": 10, ...

JsonReader reader = Json.createReader( new StringReader( out.toString() ) );
System.out.println( reader.readObject().getInt( "x" ) ); // 10
```

Soll der assoziierte Wert ein Array sein, so wird das Array mit `Json.createArrayBuilder().add(..).add(..)` aufgebaut und gefüllt.

#### JSON-Streaming API

So wie es für XML eine Pull-API gibt, existiert sie auch für JSON-Dokumente; das ist von Vorteil, wenn die Daten sehr umfangreich sind. Ein Beispiel zeigt das sehr gut:

`URL` url = new `URL`( „<https://data.cityofnewyork.us/api/views/25th-nujf/rows.json?accessType=DOWNLOAD>“ );

```java
try ( JsonParser parser = Json.createParser( url.openStream() ) ) {
while ( parser.hasNext() ) {
switch ( parser.next() ) {
```

case KEY\_NAME: case VALUE\_STRING:

```java
System.out.println( parser.getString() );
break;
```

case VALUE\_NUMBER:

```java
System.out.println( parser.getBigDecimal() );
break;
```

case VALUE\_TRUE:

```java
System.out.println( true );
break;
```

case VALUE\_FALSE:

```java
System.out.println( false );
break;
```

case VALUE\_NULL: case START\_ARRAY: case END\_ARRAY: case START\_OBJECT: case END\_OBJECT:

```
// Ignore
}
}
}
```

Zum Schreiben gibt es Vergleichbares, einen JsonGenerator; die API ist selbsterklärend:

```java
JsonGenerator gen = Json.createGenerator( System.out );
gen.writeStartArray();
gen.writeStartObject();
gen.write( "x", "12" );
gen.write( "y", "2" );
gen.writeEnd();
```

`gen.writeStartObject()`.write( „x“, „99“ ) .write( „x“, „123“ )

```java
.writeEnd();
gen.writeEnd().close();
// [{"x":"12″,"y":"2″},{"x":"99″,"x":"123″}]
```

Der JsonGenerator ist `AutoCloseable`, sodass er gut in einem try-mit-Ressoucen-Block eingesetzt werden kann.

### Objekt-JSON-Mapping

Das JSR 353 beschreibt kein automatisches Objekt-JSON-Mapping, wie JAXB das Objekt-XML-Mapping ermöglicht. Das wird im Standard JSR 367, »Java API for JSON Binding (JSON-B)« definiert. Die Website <http://json-b.net/> liefert Hintergrundinformationen, die Referenzimplementierung ist Eclipse Yasson.

Um das mit einem Beispiel testen zu können, nehmen wie Yasson in unsere POM mit auf:

```
<dependency>

<groupId>org.eclipse</groupId>

<artifactId>yasson</artifactId>

<version>1.0.1</version>

</dependency>
```

Die Dependency selbst hat eine Maven Abhängigkeit auf `javax.json.bind:javax.json.bind-api`, also der eigentliche API.

Zur Abbildung bauen wir uns ein Beispielobjekt und bringen es in das JSON-Format. Im zweiten Schritt übertragen wir den JSON-`String` wieder auf das Objekt:

```java
public class JsonbDemo {

public static class EvilLaboratory {

public String from;

public double volume;

public boolean didPayElectricityBill;

public List<String> items;

}

public static void main( String[] args ) {

EvilLaboratory lab1 = new EvilLaboratory();

lab1.from = "Frank";

lab1.didPayElectricityBill = true;

lab1.volume = 12442.33;

lab1.items = List.of( "corpses", "animals" );

Jsonb jsonbuilder = JsonbBuilder.create();

String jsonString = jsonbuilder.toJson( lab1 );

System.out.println( jsonString );

EvilLaboratory lab2 = jsonbuilder.fromJson( jsonString, EvilLaboratory.class );

System.out.printf( "from=%s, volume=%s, didPayElectricityBill=%s, items=%s",

lab2.from, lab2.volume, lab2.didPayElectricityBill, lab2.items );

}

}
```

Kategorien: [Insel](https://tutego.de/blog/javainsel/category/insel/)

[← Alle Beiträge](https://tutego.de/blog/javainsel/)

---

## Navigation

- Previous: [Insel: Apache Commons CSV](https://tutego.de/blog/javainsel/2018/07/insel-apache-commons-csv.md)
- Next: [Eigene Doclets programmatisch ausführen - was ist neu in Java 10?](https://tutego.de/blog/javainsel/2018/07/eigene-doclets-programmatisch-ausfuehren-was-ist-neu-in-java-10.md)
