JavaScript Object Notation (JSON)¶
Eine kurze Einführung zu Objekten in JavaScript haben wir bereits im JavaScript-Kapitel gegeben. Dort haben wir auch gesagt, dass wir auf die Notation solcher Objekte in JavaScript nochmal genauer eingehen wollen. Dies geschieht hier. JavaScript Object Notation (JSON) ist ein Datenaustauschformat, das einerseits einfach für Menschen zu lesen und zu schreiben ist und andererseits gut von Maschinen geparst (analysiert) und erzeugt werden kann. Ein Objekt in JSON beginnt mit einer geschweiften Klammer {
und endet mit }
. JSON besteht im wesentlichen aus Schlüssel-Werte-Paaren, die durch Komma getrennt sind.
{
"schlüssel1": wert1,
"schlüssel2": wert2,
}
Die Schlüssel sind Strings in doppelten Hochkamma (""
), dann folgt ein Doppelpunkt :
und dann folgt der Wert. Werte können Strings, Zahlen, Wahrheitswerte, Arrays, Funktionen und Objekte (und null
) sein.
Hier ein Beispiel (erweitert aus):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
- Der Wert zum Schlüssel
"name"
in Zeile2
ist ein String (string
). - Der Wert zum Schlüssel
"alter"
in Zeile3
ist eine Zahl (number
). - Der Wert zum Schlüssel
"verheiratet"
in Zeile4
ist ein Wahrheitswert (boolean
). - Der Wert zum Schlüssel
"kinder"
in Zeilen6-17
ist Array. - Die Elemente in diesem Array sind selbst wieder Objekte in JavaScript Object Notation, bestehend aus jeweils drei Schlüssel-Werte-Paaren.
- Das
"kinder"
ist numerisch indiziert, d.h. wir können über den Index0
auf das erste Kind ("Lukas"
) und über den Index1
auf das zweite Kind ("Lisa"
) zugreifen
Zugriff auf ein JSON¶
Der Zugriff auf die Werte eines JSON erfolgt mittels Punktnotation über den Schlüssel. Wir nehmen obiges Beispiel und speichern es in einer Variablen georg
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Dann können wir auf die einzelnen Werte wie folgt zugreifen:
georg.name // "Georg"
georg.alter // 47
let kinder = georg.kinder; // Array aus 2 Objekten
kinder[0].name // "Lukas"
kinder[1].name // "Lisa"
georg.biografie() // "Georg ist 47 und hat 2 Kinder."
Man kann übrigens auch anstelle der Punktnotation ein JSON wie ein assoziatives Array auffassen und z.B. anstelle von georg.name
über georg['name']
auf den Wert "Georg"
zugreifen.
Es wäre auch möglich, das "Kinder"-Array in ein weiteres JSON umzuwandeln:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Dann ist der Zugriff über den Index (also z.B. georg.kinder[0]
) nicht mehr möglich. Stattdessen aber:
georg.kinder.erstesKind.name
georg.kinder.zweitesKind.alter
Viele Objekte im Array¶
Wenn Sie viele "gleiche" Objekte speichern, dann in einem Array. Die folgende Datei zeigt viele Objekte in JSON, die in einem Array abgelegt sind:
data/members.json
{
"members": [
{
"forename": "Catherine",
"surname": "Williams",
"email": "cwilliamsl@360.cn"
},
{
"forename": "Adam",
"surname": "Anderson",
"email": "aanderson8@google.fr"
},
{
"forename": "Susan",
"surname": "Andrews",
"email": "sandrewsn@google.co.jp"
},
{
"forename": "Catherine",
"surname": "Andrews",
"email": "candrewsp@noaa.gov"
},
{
"forename": "Alan",
"surname": "Bradley",
"email": "abradley1c@globo.com"
},
{
"forename": "Anne",
"surname": "Brooks",
"email": "abrooks16@bravesites.com"
},
{
"forename": "Russell",
"surname": "Brown",
"email": "rbrownq@nifty.com"
},
{
"forename": "Ryan",
"surname": "Burton",
"email": "rburton18@foxnews.com"
},
{
"forename": "Roy",
"surname": "Campbell",
"email": "rcampbell1@geocities.com"
},
{
"forename": "Russell",
"surname": "Campbell",
"email": "rcampbell17@eventbrite.com"
},
{
"forename": "Bonnie",
"surname": "Coleman",
"email": "bcoleman11@fc2.com"
},
{
"forename": "Ernest",
"surname": "Coleman",
"email": "ecoleman15@businessweek.com"
},
{
"forename": "Richard",
"surname": "Cruz",
"email": "rcruz7@unc.edu"
},
{
"forename": "Sean",
"surname": "Cruz",
"email": "scruz10@answers.com"
},
{
"forename": "Rebecca",
"surname": "Cunningham",
"email": "rcunninghamd@mac.com"
},
{
"forename": "Margaret",
"surname": "Evans",
"email": "mevansh@pcworld.com"
},
{
"forename": "Jeffrey",
"surname": "Ford",
"email": "jford14@cnet.com"
},
{
"forename": "Andrea",
"surname": "Gardner",
"email": "agardnerv@woothemes.com"
},
{
"forename": "Deborah",
"surname": "George",
"email": "dgeorge6@furl.net"
},
{
"forename": "Sean",
"surname": "Gibson",
"email": "sgibsony@alexa.com"
},
{
"forename": "Virginia",
"surname": "Graham",
"email": "vgrahamk@aol.com"
},
{
"forename": "Steven",
"surname": "Hamilton",
"email": "shamiltonu@state.tx.us"
},
{
"forename": "Virginia",
"surname": "Hawkins",
"email": "vhawkinsf@ehow.com"
},
{
"forename": "Edward",
"surname": "Hicks",
"email": "ehicksc@pcworld.com"
},
{
"forename": "Mark",
"surname": "Johnson",
"email": "mjohnsonj@hostgator.com"
},
{
"forename": "Ruth",
"surname": "Jordan",
"email": "rjordan1a@smugmug.com"
},
{
"forename": "Antonio",
"surname": "Kim",
"email": "akim4@odnoklassniki.ru"
},
{
"forename": "Jennifer",
"surname": "Marshall",
"email": "jmarshallt@gnu.org"
},
{
"forename": "Eric",
"surname": "Matthews",
"email": "ematthews5@independent.co.uk"
},
{
"forename": "Raymond",
"surname": "Mcdonald",
"email": "rmcdonald2@ihg.com"
},
{
"forename": "Eric",
"surname": "Miller",
"email": "emillere@creativecommons.org"
},
{
"forename": "Jonathan",
"surname": "Morales",
"email": "jmoralesa@ovh.net"
},
{
"forename": "Marie",
"surname": "Morgan",
"email": "mmorganb@cloudflare.com"
},
{
"forename": "Amanda",
"surname": "Nelson",
"email": "anelson13@indiatimes.com"
},
{
"forename": "Lisa",
"surname": "Olson",
"email": "lolsonr@telegraph.co.uk"
},
{
"forename": "Alice",
"surname": "Ortiz",
"email": "aortizw@histats.com"
},
{
"forename": "Peter",
"surname": "Phillips",
"email": "pphillipss@1688.com"
},
{
"forename": "Matthew",
"surname": "Porter",
"email": "mporter9@europa.eu"
},
{
"forename": "Tammy",
"surname": "Ray",
"email": "trayx@weather.com"
},
{
"forename": "Mark",
"surname": "Richardson",
"email": "mrichardson1d@ihg.com"
},
{
"forename": "Joan",
"surname": "Roberts",
"email": "jroberts12@alibaba.com"
},
{
"forename": "Kathleen",
"surname": "Rose",
"email": "kroseg@pinterest.com"
},
{
"forename": "Steve",
"surname": "Sanders",
"email": "ssanders1b@wikispaces.com"
},
{
"forename": "Shirley",
"surname": "Scott",
"email": "sscottm@macromedia.com"
},
{
"forename": "Lillian",
"surname": "Stephens",
"email": "lstephens19@hugedomains.com"
},
{
"forename": "Nicole",
"surname": "Thompson",
"email": "nthompson3@admin.ch"
},
{
"forename": "Marie",
"surname": "Thompson",
"email": "mthompsonz@yelp.com"
},
{
"forename": "Alan",
"surname": "Vasquez",
"email": "avasquezo@miibeian.gov.cn"
},
{
"forename": "Mildred",
"surname": "Watkins",
"email": "mwatkins0@miibeian.gov.cn"
},
{
"forename": "Eugene",
"surname": "Williams",
"email": "ewilliamsi@deliciousdays.com"
}
]
}
Ein Array ist stets numerisch indiziert, d.h. Sie können unter Verwendung des Index die einzelnen Objekte auslesen. Wir hatten das oben bereits für das "kinder"
-Array gezeigt, geben hier aber noch ein Beispiel an:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
Es entsteht eine Liste aus Hyperlinks, wobei jeder Hyperlink in der Form zusammengesetzt ist: mailto:email-adresse
. Es sind sogar noch subject
(also Betreff) und body
(als Nachrichteninhalt) angehängt, d.h. die Form ist mailto:email-adresse?subject=Webtech&body=Hallo%20FIW!
. Beachten Sie, dass es sich dabei um eine URL handelt und diese deshalb URL encoded sein muss, d.h. dass z.B. Leerzeichen durch %20
ersetzt werden.
Die Seite sieht dann so aus:
Und wenn man auf einen Link klickt (z.B. Adam Anderson
), öffnet sich das Mailprogramm:
Ajax¶
Ajax steht für Asynchronous JavaScript and XML. Es wird verwendet, um Daten vom Server zu laden oder an den Server zu senden, ohne die Seite neu zu laden. Ajax ist somit die Basis für eine Single Page Application. Obwohl XML im Namen von Ajax vorkommt, wird hauptsächlich JSON als Datenaustauschformat für das Senden und Empfangen von Daten zwischen Client und Server verwendet.
Der Begriff asynchron beschreibt, dass der Austausch nicht die Webseite blockiert, d.h. dass weitere Nutzerinteraktionen möglich sind während der Datenaustausch erfolgt.
XMLHttpRequest¶
Der Grundbaustein von Ajax ist ein XMLHttpRequest
-Objekt. Ein solches Objekt stellt Methoden zur Verfügung, um
- eine Webseite (per JavaScript) aktualisieren zu können, ohne sie neu zu laden,
- Daten vom Server anzufordern nachdem die Seite geladen ist,
- Daten zu einem Server im Hintergrund zu senden.
Angenommen, folgende JSON-Datei liegt auf unserem Server (DocumentRoot ist mein DocumentRoot-Ordner):
{
"name": "Georg",
"alter": 47,
"verheiratet": false,
"beruf": null,
"kinder": {
"erstesKind": {
"name": "Lukas",
"alter": 19,
"schulabschluss": "Gymnasium"
},
"zweitesKind": {
"name": "Lisa",
"alter": 14,
"schulabschluss": null
}
}
}
Client-seitig besteht die Anfrage an einen Webeserver per XMLHttpRequest
aus drei Schritten:
XMLHttpRequest
-Objekt erzeugen- Anfrage (Request) an Server senden
- Antwort (Response) verarbeiten/ausgeben
Wir schauen uns das an einem Beispiel an:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
- In Zeile
10
definieren wir uns einen Button, der an den EventListener für dasclick
-Ereignis angemeldet ist. In der Ereignisbehandlung wird die FunktionloadJSON()
aufgerufen. - In Zeile
13
wird dasXMLHttpRequest
-Objekt erzeugt. Die Referenz darauf speichern wir in der Variablenxhttp
. - In Zeile
18
wird die Verbindung zum Webserver hergestellt und der Request konfiguriert. Dieopen()
-Funktion desXMLHttpRequest
-Objektes enthält drei Parameter:- der erste Parameter beschreibt die http-Methode, mit der angefragt werden soll (
"GET"
oder"POST"
) - der zweite Parameter gibt die Zieladresse der angefragten Ressource auf dem Server an
- der dritte Parameter gibt die Art der Kommunikation an (
true
: asynchron, `false: synchron)
- der erste Parameter beschreibt die http-Methode, mit der angefragt werden soll (
- In Zeile
19
wird diese Anfrage (Request) gesendet - In den Zeilen
14-17
wird für dieonreadystatechange
-Eigenschaft desXMLHttpRequest
-Objektes eine Funktion definiert, die immer dann (automatisch) aufgerufen wird, wenn sich derreadyState
desXMLHttpRequest
-Objektes ändert.readyState
kann folgende Werte annehmen:0
(UNSENT
):open()
wurde noch nicht aufgerufen1
(OPENED
):send()
wurde noch nicht aufgerufen2
(HEADERS_RECEIVED
):send()
wurde aufgerufen und Headers sowie Status sind verfügbar3
(LOADING
): Download ist im Gange;responseText
enthält bereit sunvollständige Daten4
(DONE
): Download-Vorgang abgeschlossen
- wenn
readyState
den Wert4
hat und der http-Status200
(OK
) ist (Zeile15
), dann ist der Download der angefragten Ressource fertig und die Ressource kann verwendet werden. Dazu wird in Zeile16
die FunktioncreateFormular(json)
aufgerufen dabei dasXMLHttpRequest
-Objekt übergeben - in der Eigenschaft
responseText
desXMLHttpRequest
-Objektes ist das heruntergeladene JSON enthalten. Dies wird in Zeile23
in der FunktioncreateFormular(json)
ausgelesen - die JavaScript-Funktion
JSON.parse()
erzeugt aus einem JSON-formatierten Text ein entsprechendes Javascript-Objekt. Dies geschieht ebenfalls in Zeile23
. Die referenz auf dieses JavaScript-Objekt wird in der Variablengeorg
gespeichert. - in den Zeilen
24-26
sind einige Zugriffe auf das Objekt exemplarisch implementiert. Die Ausgabe erfolgt auf die Konsole. Wenn Sie das Beispiel also ausprobieren, dann schauen Sie auf die Konsole in Ihren DeveloperTools.
fetch()
-API¶
In den letzten Jahren wurde eine sogenannte fetch()
-API entwickelt, die leistungsfähigere und flexiblere Funktionen zur Verfügung stellt, als ein XMLHttpRequest
-Objekt. Da wir näher auf Promises eingehen müssten, erwähnen wir das Thema hier nur und geben ein Beispiel an, das dem oberen sehr ähnlich ist:
function loadJSONmitFetch() {
fetch('http://localhost/Webtech20/georg.json')
.then(
function(response) {
if (response.status !== 200) {
console.log('Warning! Status Code: ' + response.status);
return;
}
// Lese json aus der response aus
response.json()
.then(
function(data) {
console.log(data);
}
);
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
}