JSON und REST-API
Das Abholen von Daten mit GET ist definitiv die am meist benutzte HTTP-Methode, aber GET ist immer eine lesende Methode. Wenn Daten nicht nur gelesen werden, sondern auch geändert, neue Daten erzeugt oder gelöscht werden sollen, kommen zudem HTTP-Methoden wie POST, PUT, PATCH und DELETE zum Einsatz. Beispiele sind das Anlegen von Benutzerdaten mit POST, während PUT Benutzerdaten vollständig aktualisiert oder ersetzt. PATCH hingegen aktualisiert nur einen Teil eines Datensatzes, meist um den Datentransfer im Vergleich gegenüber einem PUT zu reduzieren.
GET | lesender Zugriff auf Daten |
POST | Anlegen von Daten |
PUT | Vollständiges Überschreiben vorhandener Daten |
PATCH | Teilweises Überschreiben vorhandener Daten |
DELETE | Löschen von Datensätzen |
Anders als beim Lesen von JSON-Daten braucht fetch() bei POST, PUT, PATCH die URL der Anwendung und die Optionen headers und body. Ein POST-Request kann eine body-Option haben, die einen String (hier JSON stringify) aufnimmt.
Mit dem fetch-API holt eine Anwendung Daten von einem Server über ein RESTful API. Das asynchrone fetch-API nutzt Promises, so dass die Anwendung entweder auf Antworten wartet (async await) oder Promise Chaining nutzt. fetch () übergibt einen RESTful-Endpoint (eine URL) als erstes Argument. Das zweite Argument ist ein Objekt (wird bei einem GET-Request nicht benötigt) mit drei Schlüsseln:
- method
- GET, POST, PUT, PATCH, DELETE
- body
- Informationen, die als Request gesendet werden (nicht bei GET-Request). Mit body muss auch immer der entsprechende Inhaltstyp {'Content-Type' : 'application/json'} angegeben werden.
- headers
- Metadaten zum Typ der Daten und i.d.R. API-Keys für die Authentifizierung.
DummyJSON – Üben und Erforschen
Auf DummyJSON gibt es REST-Endpoints mit JSON-Daten für die Entwicklung mit Javascript, jQuery, React, …, die als Platzhalter agieren. Schön für Fingerübungen.
DummyJSON stellt Testdaten für Themen wie Produkte, Benutzerdaten, Rezepte und Kommentare bereits. Das Projekt ist gut dokumentiert und kommt mit vielen Beispielen.
fetch: JSON-Datensätze ändern und speichern
Meistens wird JSON aus Datenquellen gelesen, in interaktiven Seiten aber auch geändert und als JSON an ein REST-API (z.B. eine PHP-Anwendung auf dem Server) zurückgegeben.
Anders als beim Lesen der JSON-Datei mit dem einfachen fetch ("data.json") braucht fetch() beim Senden von JSON die URL der Anwendung und die Optionen POST, headers und body.
Dieses spartanische Beispiel ändert Beiträge (Posts) von Benutzern und kann Taxonomie-Tags entfernen.
Edit | Delete | Titel |
Response
Schon ein kleines, nur groß angerissenes Projekt wie dieses Beispiel bringt einen komplexen Ablauf, denn wir müssen immer wieder auf die Response warten. Dabei ist das Erstellen eines neuen Posts im Beispiel nicht einmal enthalten, die Eingaben werden nicht geprüft, Benutzer-Auth ist nicht implementiert.
- Abholen der Datensätze mit fetch,
- dann Platzieren der Daten im DOM,
- dann Beobachten der Benutzeraktionen,
- dann Reagieren auf Edit oder Delete,
- dann – erst wenn Edit aktiv ist – den Editor mit Daten füllen,
- optional: dann kann ein Tag gelöscht werden (neue Tags ist nicht implementiert),
- dann kann ein Post geändert und versendet werden.
Beim Abholen muss GET nicht angegeben werden. Das Beispiel liest die Posts des Users mit der userId 5. listPosts (elem) erstellt die Liste der Datensätze für User 5 sowie die den Edit- und Delete-Buttons.
function postEditor () {
Endpunkt
┌───────────────┴────────────────┐
│ │
▼ ▼
fetch('https://dummyjson.com/posts/user/5')
.then(res => res.json())
.then(res => {
// Platzieren der Daten im DOM
res.posts.forEach (elem => listPosts (elem));
return res.posts;
})
Ein eventListener für Klicks auf Edit / Delete. editor(obj) schreibt die Werte in die Felder des Editors,
deletePost(entry) löscht den Datensatz.
.then (posts => {
// Datensatz editieren
edit.forEach ( btn => {
btn.addEventListener ("click", function () {
const obj = posts.find ((elem) => elem.id === Number(id));
editor (obj);
})
});
// Datensatz löschen
del.forEach ( btn => {
btn.addEventListener ("click", function () {
const entry = posts.find ((elem) => elem.id === Number(id));
deletePost (entry);
});
});
})
Ein POST- / PUT-Request kann eine body-Option haben, die einen String (hier JSON stringify) aufnimmt. Mit body muss auch immer der entsprechende Inhaltstyp {'Content-Type' : 'application/json'} angegeben werden.
Für ein Update des Datensatz braucht fetch die Optionen PUT, headers und body. Die Daten gehen in body.
function updatePost (id) { fetch(`https://dummyjson.com/posts/${id}`, { method: 'PUT', /* or PATCH */ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ "title": document.querySelector ("#title").value, "body": document.querySelector ("#content").value, "tags": tags }) }) .then(res => res.json()) .then(console.log); }
Natürlich speichert DummyJSON Änderungen nicht wirklich. Statt dessen dienen der Rückgabewert und die Response vom Server (Konsole > Netzwerk > Headers) als Bestätigung.