REST API Anbindung mit Synesty

Einleitung

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 Cookbookopen in new window beschreibt den Unterschied der drei Steps.

Beispiel API

Für die Beispiele nutzen wir den Service von https://my-json-server.typicode.com/open in new window, 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/demoopen in new window , 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
ARC (Advanced REST Client) https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo?hl=deopen in new window
oder POSTMAN (https://www.getpostman.com/open in new window)

1. GET Request

Der einfachste Fall ist ein sog. HTTP GET Request.

https://my-json-server.typicode.com/typicode/demo/postsopen in new window

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/1open in new window

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-restopen in new window

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 APICallopen in new window 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()open in new window.

ParameterWertBeschreibung
host

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

die URL des GET Request
methodGET
responseFormatJSONDamit 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 Videoopen in new window

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
open in new window
https://my-json-server.typicode.com/typicode/demo/posts/3open in new window

Dazu verwenden wir den Step SpreadsheetURLDownloadopen in new window, 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 Videoopen in new window

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 APICallopen in new window Step, da es sich um einen einzelnen Request handelt.

ParameterWertBeschreibung
host

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

die URL des GET Request
methodPOST
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.

responseFormatJSONDamit sagen wir, dass die Antwort im JSON Format zurück kommt.
parsingTemplateParsing 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 SpreadsheetURLDownloadopen in new window, 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

Merke: Die Platzhalter funktionieren nicht nur im requestBody sondern auch in host oder requestHeaders. D.h. auch die URL oder die HTTP-Header kann man dynamisch aus den Spalten-Inhalten zusammenbauen.*
*Immer den +-Button an den Feldern verwenden! Damit erhält man die verfügbaren 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 erlaubtopen in new window 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_stringopen in new window 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
StringToFileHiermit erzeugen wir die Test-CSV-Datei.
CSVReader
Step-Vorschau:
Damit wird die CSV-Datei in ein Spreadsheet eingelesen.
SpreadsheetURLDownload


Step Vorschau:

Hier sieht man, dass 2 POST Requests gesendet wurden, mit 2 unterschiedlichen JSON-Objekten... jeweils mit den Werten aus der CSV-Datei.

Hinweis: Nicht wundern. in responseContent taucht zwei mal 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 wir pro ArtikelID ein GET-Request gemacht.
Achten Sie, 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 .


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.

JSONReader


Step Vorschau:

Da die JSON-Response nur die ID beinhaltet, erhalten wir auch nur eine Spalte im Spreadsheet.


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 Videoopen in new window

Komplettes Projekt zum Nachstellen

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