Skip to content

REST API Anbindung mit Synesty

In diesem Tutorial lernen Sie Schritt für Schritt, wie man mit Synesty Basis-Bausteinen eine individuelle REST-API mit JSON als Datenaustauschformat anbinden kann.
Synesty verfügt über Bordmittel (Steps), mit denen Sie in der Lage sind jeder beliebige REST-API per HTTP anzubinden. Das heißt, dass Sie nicht abhängig von den Add-Ons sind, die Synesty bereitstellt, sondern auch völlig andere APIs individuell anbinden können. 

Bordmittel

Die wichtigen Steps für eine API-Anbindung sind:

Unterschied zwischen APICall, SpreadsheetURLDownload und URLDownload

Dieses Cookbook beschreibt den Unterschied der drei Steps.

Beispiel API

Für die Beispiele nutzen wir den Service von https://my-json-server.typicode.com/, der es erlaubt eine REST-API zu simulieren. Das ist notwendig, da die REST-APIs
der meisten Systeme umfangreichere Voraussetzungen und Einrichtung benötigen, bevor man diese benutzen kann. Das wäre für so ein Tutorial nicht hilfreich. Deshalb bauen wir auf die Beispiele von https://my-json-server.typicode.com/typicode/demo , die ein Blog mit Artikeln (Posts) und Kommentaren (Comments) simulieren.

API Calls testen

Zum Ausprobieren der obigen Beispiele ohne Synesty Studio empfehlen wir Ihnen ein Tool wie z.B. den
Advanced REST Client oder POSTMAN

1. GET Request

Der einfachste Fall ist ein sog. HTTP GET Request.

https://my-json-server.typicode.com/typicode/demo/posts

Diese URL gibt eine Liste von Artikeln (sog. Posts) zurück:

Antwort der REST-API

[
{
"id": 1,
"title": "Post 1"
},
{
"id": 2,
"title": "Post 2"
},
{
"id": 3,
"title": "Post 3"
}
]

1.1. Einzelnen Artikel mit GET abrufen

Um die Daten eines einzelnen Artikels abzurufen, können Sie folgende URL verwenden:

https://my-json-server.typicode.com/typicode/demo/posts/1

Diese URL ruft den Artikel mit der ID=1 ab. 

Antwort der REST-API

{
"id": 1,
"title": "Post 1"
}

In diesem Fall bekommen wir einen einzelnen Artikel, statt einer Liste.

2. POST Request

Ein HTTP-POST Request wird meistens genutzt, um Objekte neu zu erstellen oder zu modifizieren.
Bei einem POST-Request übergibt man eine JSON-Payload, mit dem Objekt, welches angelegt werden soll.

In der Literatur findet man auch PUT zum Erstellen, wobei die Meinungen darüber sehr stark variieren, siehe https://stackoverflow.com/questions/630453/put-vs-post-in-rest

Bezogen auf das Beispiel mit den Artikeln, könnte man mit folgendem POST Request einen neuen Artikel anlegen.
Der Artikel besteht aus Titel, Text, Kategorie und einem Flag für Sichtbarkeit:

Request

{
"title": "my first post" ,
"text": "this is my first text",
"category": 1,
"visible": true
}

Die Antwort des Servers ist wiederum ein JSON, der die ID des neu angelegten Artikels beinhaltet.

Antwort der REST-API

{
"id": 4
}

3. Beispiele mit Synesty Studio umsetzen

In diesem Abschnitt wollen wir nun die obigen Beispiele mit Synesty Studio umsetzen. 

3.1. GET Request mit Einlesen der Antwort

Dazu benutzen wir den APICall Step.
Damit können wir den GET Request absetzen und auch die Antwort mit dem *parsingTemplate *einlesen und in ein Spreadsheet umwandeln. 
die wichtigste Zeile im *parsingTemplate ist addColumns().

Parameter Wert Beschreibung
host

https://my-json-server.typicode.com/typicode/demo/posts

die URL des GET Request
method GET
responseFormat JSON Damit sagen wir, dass die Antwort im JSON Format zurück kommt.
parsingTemplate

Parsing Script für REST-API Antwort

<#assign row = target.addRow()>
<#list json as j >
<#assign row = target.addRow()>
${addColumns(row, j)}
</#list>

Hiermit wird die Antwort eingelesen.

Die erste Zeile <#assign row = target.addRow()> fügt dem Ergebnis-Spreadsheet eine leere Kopfzeile hinzu (das ist notwendig).

Die Variable json ist ein Platzhalter des Steps, der das JSON-Objekt repräsentiert.
Im konkreten Beispiel kommt ein JSON-Array mit Objekte zurück.

Die <#list> Anweisung iteriert über jedes Objekt des Arrays. Mit der alias-Variable j greifen Sie auf auf das einzelne Objekt (Array-Element) zu.
Der Ausdruck <#assign row = target.addRow()> fügt dem Ergebnis-Spreadsheet eine neue Zeile hinzu. Das Zeilen-Objekt steht durch assign in der Variable row zur Verfügung.

Die addColumns() Funktion fügt nun alle Felder des JSON-Objekts j der Zeile row hinzu.

Beispiel Video:

Zum Video

3.2. Mehrere GET Requests basierend auf einem Spreadsheet ausführen

Das nächste Beispiel geht davon aus, dass man eine eine Liste mit Artikel-IDs hat und pro Artikel-ID die Informationen abrufen will. 
Die besagte Liste kommt aus einer CSV-Datei, die in ein Spreadsheet eingelesen wird. 
articles.csv

artikelID
1
3

Diese CSV Datei ist sehr simpel und besteht nur aus einer Spalte. Darin enthalten sind 2 Artikel-IDs 1 und 3.

Ziel: Pro Zeile soll ein GET-Request ausgeführt werden, jeweils für die entsprechende Artikel-ID.
D.h. wir erwarten folgende 2 GET-Requests:

https://my-json-server.typicode.com/typicode/demo/posts/1
https://my-json-server.typicode.com/typicode/demo/posts/3

Dazu verwenden wir den Step SpreadsheetURLDownload, da dieser Step pro Spreadsheet-Zeile einen Request ausführen kann. 

StringToFile

Hiermit erzeugen wir die Test-CSV-Datei.

CSVReader

Damit wird die CSV-Datei in ein Spreadsheet eingelesen.

SpreadsheetURLDownload

Step-Vorschau:

Da der SpreadsheetURLDownload Step keine JSON-Parsing Möglichkeit bietet (im Gegensatz zum APICall) verwenden wir den JSONReader Step, um die einzelnen JSON-Antworten zu verarbeiten. Der JSONReader kann mit mehreren Inputs umgehen, d.h. in diesem Fall liegen 2 JSON-Antworten in der responseContent Spalte vor (da ja 2 GET-Requests gemacht wurden… ein Request pro Artikel). Beispiel Video:

Zum Video

3.2. Einzelner POST Request 

Aufbauend auf dem Szenario 3.1. wollen wir nun einen einzelnen POST Request ausführen um z.B. einen neuen Artikel zu erstellen. Die Antwort wollen wir auch wieder einlesen, um Sie weiterverarbeiten zu können. 

Dazu benutzen wir wieder APICall Step, da es sich um einen einzelnen Request handelt. 

Parameter Wert Beschreibung
host

https://my-json-server.typicode.com/typicode/demo/posts

die URL des GET Request
method POST
requestBody

Request

{
"title": "my first post" ,
"text": "this is my first text",
"category": 1,
"visible": true
}

Das (Phantasie)-JSON-Objekt für einen neuen Artikel.

responseFormat JSON Damit sagen wir, dass die Antwort im JSON Format zurück kommt.
parsingTemplate Parsing Script für REST-API Antwort
<#assign row = target.addRow()>
<#list json as j >
<#assign row = target.addRow()>
${addColumns(row, j)}
</#list>

Hiermit wird die Antwort eingelesen.

Die erste Zeile <#assign row = target.addRow()> fügt dem Ergebnis-Spreadsheet eine leere Kopfzeile hinzu (das ist notwendig).

Die Variable json ist ein Platzhalter des Steps, der das JSON-Objekt repräsentiert.
Im konkreten Beispiel kommt ein JSON-Array mit Objekte zurück.

Die <#list> Anweisung iteriert über jedes Objekt des Arrays. Mit der alias-Variable j greifen Sie auf auf das einzelne Objekt (Array-Element) zu.
Der Ausdruck <#assign row = target.addRow()> fügt dem Ergebnis-Spreadsheet eine neue Zeile hinzu. Das Zeilen-Objekt steht durch assign in der Variable row zur Verfügung.

Die addColumns() Funktion fügt nun alle Felder des JSON-Objekts j der Zeile row hinzu.

requestHeaders
Content-type=text/json
Das kann sich je nach REST-API unterscheiden. Unsere Test-API braucht Content-type=text/json, ansonsten liefert der Server ein 500 Internal server error.
Das POST-Beispiel ist nahezu identisch mit dem GET-Beispiel. Der Unterschied ist der *requestBody*, der bei POST definiert werden kann. 

3.3. Mehrere POST Requests

Praktisch relevanter ist ein Beispiel, in dem mehrere POST ausführt, um z.B. mehrere Artikel anzulegen oder zu aktualisieren.
Wir setzen hier wieder auf das vorangegangene Beispiel mit mehreren GET-Requests auf und adaptieren es für POST. 

Dazu ändern wir unsere CSV-Datei etwas ab, mit Feldern aus dem Einzel-POST-Request Beispiel:

articles.csv

title;text;category;visible
"my first post";"this is my first text";"1";"true"
"my second post";"this is my second text";"2";"false"

Ziel: Pro Zeile soll ein POST-Request ausgeführt werden und jeweils ein neuer Artikel mit den jeweiligen Daten (title, text, category, visible) erzeugt werden. 

D.h. wir erwarten folgende 2 POST-Requests:

Request 1

POST https://my-json-server.typicode.com/typicode/demo/posts/

{
"title": "my first post" ,
"text": "this is my first text",
"category": 1,
"visible": true
}

Request 2

POST https://my-json-server.typicode.com/typicode/demo/posts/

{
"title": "my second post" ,
"text": "this is my second text",
"category": 1,
"visible": true
}

Dazu verwenden wir wieder den Step SpreadsheetUrlDownload, da dieser Step pro Spreadsheet-Zeile einen Request ausführen kann. 
Dieses mal allerdings mit POST (statt GET) und einem dynamischen requestBody mit den Daten aus der CSV-Datei. 

Dynamischer requestBody 

Im requestBody verwenden wir Variablen, die durch den Spaltenwert der jeweiligen Input-Spreadsheet-Zeile ersetzt wird:

Request mit Platzhalter-Variablen

{
"title": "${title!}" ,
"text": "${text!}",
"category": ${category!},
"visible": ${visible!}
}

Die verwendeten Platzhalter-Variablen werden bei der Ausführung durch den Spalten-Wert aus der Spreadsheet-Zeile ersetzt - d.h. in der ersten Zeile wird ${title!} zu “my first post”, in der zweiten wird *${title!} *zu *“my second post” *usw.
Der Screenshot des SpreadsheetURLDownload zeigt das ebenfalls nochmal.

Infos zu Platzhalter-Variablen

Ungültige JSON-Zeichen aus Platzhaltern entfernen

Wenn man im requestBody eine JSON-Payload zusammenbaut, dann kann es vorkommen, dass im Wert eines Platzhalters Zeichen vorkommen, die in JSON aber nicht erlaubt sind bzw. erst “escaped” werden müssen. D.h. die Gegenseite (API) würde den Request vermutlich mit einer Fehlermeldung ablehnen (z.B. “Bad Request”).

Um das zu vermeiden, sollten Sie bei Text-Variablen das ?json_string Built-In von Freemarker verwenden.
D.h. der obige requestBody, sollte wie folgt umformuliert werden, damit man auf der sicheren Seite ist:

Request mit Platzhalter-Variablen und Escaping

{
"title": "${title!?json_string}" ,
"text": "${text!?json_string}",
"category": ${category!},
"visible": ${visible!}
}

Warum kein ?json_string bei category und visible?

In unserem Beispiel ist category immer eine Zahl und visible immer true oder false. D.h. wir wissen, dass da niemals ungültige JSON-Zeichen drin stehen. ?json_string ist immer bei langen Strings sinnvoll wie z.B. product_description.

StepKonfigurationBeschreibung
StringToFileKonfigurationHiermit erzeugen wir die Test-CSV-Datei.
CSVReaderKonfiguration
Step-Vorschau:
Step Vorschau
Damit wird die CSV-Datei in ein Spreadsheet eingelesen.
SpreadsheetURLDownloadKonfiguration Weitere Einstellungen
Step Vorschau:
Hier sieht man, dass 2 POST Requests gesendet wurden, mit 2 unterschiedlichen JSON-Objekten, jeweils mit den Werten aus der CSV-Datei. Step Vorschau
Hinweis: Nicht wundern. In responseContent taucht zweimal id=4 auf. Das liegt an der Test-REST-API, die immer die gleiche Antwort liefert, da in Wirklichkeit kein neuer Artikel angelegt wird. Bei einer echten API würde vermutlich immer ein neuer Artikel mit einer neuen ID erzeugt werden.
Hiermit wird pro ArtikelID ein GET-Request gemacht.
Achten Sie darauf, dass die URL (host) dynamisch erzeugt wird. Am Ende sehen Sie die ${articleID}-Variable aus dem Spreadsheet des vorherigen CSVReader Steps. Die Variablen (Spalten) erhalten Sie durch Klick auf Variable wählen.
Den outputMode sollten Sie auf “Add response content to output spreadsheet” setzen, damit die JSON-Response auch in der Vorschau der Antwort auftaucht.
Das Ergebnis des Steps ist ein Spreadsheet mit verschiedenen Dingen aus der HTTP-Response und u.a. der Spalte responseContent, die den für uns interessanten JSON-Inhalt beinhaltet.
JSONReaderKonfiguration
Step Vorschau:
Da die JSON-Response nur die ID beinhaltet, erhalten wir auch nur eine Spalte im Spreadsheet.
Step Vorschau
Da der SpreadsheetURLDownload Step keine JSON-Parsing Möglichkeit bietet (im Gegensatz zum APICall), verwenden wir den JSONReader Step, um die einzelnen JSON-Antworten zu verarbeiten.
Der JSONReader kann mit mehreren Inputs umgehen, d.h. in diesem Fall liegen 2 JSON-Antworten in der responseContent-Spalte vor (da ja 2 GET-Requests gemacht wurden… ein Request pro Artikel).

Beispiel Video: Dieses Video zeigt den wichtigen Teil, wo der JSON-Request aus den Daten der CSV-Datei zusammengebaut wird. Dabei wird zuerst das statische JSON-Beispiel genommen und sukzessive durch die Variablen ersetzt. 

Zum Video

Komplettes Projekt zum Nachstellen

Das hier gezeigte Projekt steht als Vorlage zur Verfügung und kann in Ihrem Account installiert werden.