Dienstag, 16. Oktober 2018

VFP, das Web und der ganze ReST - 2 - Wer ReST sagt sagt auch JSON / VFP, the web and all the ReST - 2 - In for a ReST, in for a JSON

2. Wer ReST sagt, sagt auch JSON


Die JavaScript Object Notation kurz JSON ist bei heutigen REST APIs der Quasi-Standard zur Übertragung kompakter Informationen. Sie verzichtet auf den für XML üblichen Overhead von Typdeklarationen und Tags und reduziert sich auf wenige Symbole und Zeichen zur Feld- und Datensatztrennung. Somit handelt es sich bei JSON nicht um eine struktur-beschreibende Sprache (wie XML) sondern um eine nicht deklarative Syntax-Konvention. Hierdurch erreicht sie zugleich eine hohe Lesbarkeit. Für Web-Entwickler ist die mit JSON einhergehende Javascript-Validität ein weiterer nicht zu unterschätzender Vorteil.

Für Einsteiger kann der Besuch verschiedener Seiten zum Thema JSON jedoch schnell zu Irritationen führen. Mal werden Namen und Werte mit und mal ohne Anführungszeichen dargestellt. Bisher war für mich die von Mozilla vorgegebene Definition diejenige welche immer funktionierte.

https://developer.mozilla.org/de/docs/Learn/JavaScript/Objects/JSON

Mit Hilfe der folgenden Beispiele möchte ich die Strukturen von JSON kurz erklären:
Ein einfaches JSON Objekt beginnt mit einer geschwungenen Klammer "{" und endet mit einer geschwungenen Klammer "}" (curly brackets). Innerhalb dieses Objekts befinden sich durch Komma getrennte Name:Wert Paare. Es kommt auch vor das für diese Objekte der Begriff der Collection genutzt wird.

Beispiel 1:

{ "ersterName" : "ersterWert" , "zweiterName" : 2 }

Bei größeren Datenmengen ist es durchaus sinnvoll, diese im Editor lesbarer zu gestalten:

Beispiel 2a: Unformatiertes JSON 

[{"textFeld": "ersterWert","zahlenFeld1": 2,"zahlenFeld2": 12.345,"booleanFeld1": "true","booleanFeld2": "false","nullFeld": "null","arrayFeld1": [1, 2, 3, 4],"arrayFeld2": ["a", "b", "c"],"arrayObject": [{"textFeld": "Wert","zahlenFeld": 2}]},{"textFeld": "zweiterWert","zahlenFeld1": 3,"zahlenFeld2": 45.678,"booleanFeld1": "false","booleanFeld2": "true","nullFeld": "null","arrayFeld1": [5, 6, 7, 8],"arrayFeld2": ["d", "e", "f"],"arrayObject": [{"textFeld": "Wert2","zahlenFeld": 22}]}]

Derselbe JSON String in formatierter Darstellung ist dagegen um ein vielfaches lesbarer:

Beispiel 2b: Formatiertes JSON

[
 {
  "textFeld" : "ersterWert" ,
  "zahlenFeld1" : 2 ,
  "zahlenFeld2" : 12.345 ,
  "booleanFeld1" : "true" ,
  "booleanFeld2" : "false" ,
  "nullFeld" : "null" ,
  "arrayFeld1" : [ 1 , 2 , 3 , 4 ] ,
  "arrayFeld2" : [ "a" , "b" , "c" ] ,
  "arrayObject" : [ {
      "textFeld" : "Wert" ,
      "zahlenFeld" : 2
    } ]

 },

 {
  "textFeld" : "zweiterWert" ,
  "zahlenFeld1" : 3 ,
  "zahlenFeld2" : 45.678 ,
  "booleanFeld1" : "false" ,
  "booleanFeld2" : "true" ,
  "nullFeld" : "null" ,
  "arrayFeld1" : [ 5 , 6 , 7 , 8 ] ,
  "arrayFeld2" : [ "d" , "e" , "f" ] ,
  "arrayObject" : [ {
    "textFeld" : "Wert2" ,
    "zahlenFeld" : 22
    } ]

 }
]


Auffällig hierbei ist, dass die Trennung durch Kommata immer Gültigkeit im jeweiligen Kontext besitzt. D.h. nicht nur Name:Wert Paare werden durch Komma voneinander getrennt, sondern auch Arrays und Objekte.

Werden mehrere Objekte oder einzelne Arrays übergeben, so müssen diese grundsätzlich in eckigen Klammern [ ] (square brackets) gekapselt werden. In Beispiel 2 ist das gesamte Konstrukt aus diesem Grund in eckige Klammern gesetzt denn es werden zwei Objekte (Datensatz 1 und 2) übergeben. Die Name:Wert Paare für arrayFeld1 und arrayFeld2 werden als Arrays übergeben und somit steht der Wert in eckigen Klammern und da der Wert des Feldes arrayObjekt mehrere Objekte übergibt müssen diese ebenfalls in eckige Klammern gepackt werden.

Zum Prüfen eines eigenen JSON Objektes/Arrays ist es sinnvoll ein solches Konstrukt validieren zu lassen. Auf https://jsonlint.com/ ist dies ohne Probleme möglich. Dort wird das eingefügte JSON Objekt auch gleich optisch aufpoliert. 

Eine solche Validierung ist aus meiner Sicht zwingend. Ein einfaches Komma, egal ob zu viel oder zu wenig, führt dazu, dass der Webservice einen Fehler melden wird, denn Webservices haben eine Null-Fehler-Toleranz und das ist auch gut so!

Das obige Beispiel (2a/2b) stellt letztlich einen einfachen JSON Array dar. Eine Objektliste mit mehreren Datensätzen, wenn man so möchte. Ein solches Konstrukt macht dann Sinn, wenn es sich um einen spezialisierten Service handelt. Will heißen, es gibt immer nur diesen Aufbau. Sobald der Service jedoch unterschiedliche Datenobjekte liefern kann, beispielsweise  Adressen, Mitarbeiter einer speziellen Adresse, Aufträge usw. dann wird ein Identifier benötigt der es ermöglicht, anhand seines Wertes zu erkennen, wie die Daten aufgebaut sind.

Kehren wir also zum vorherigen Beispiel zurück und bohren es um eine solche Funktion auf. Aus dem mit  [ ] geklammerten Objektarray wird umgehend ein einfacher Wert der in ein Name:Wert Paar eingegliedert wird.

Beispiel 3: 



{
  "varianteEins" : [
  {
    "textFeld" : "ersterWert" ,
    "zahlenFeld1" : 2 ,
    "zahlenFeld2" : 12.345 ,
    "booleanFeld1" : "true" ,
    "booleanFeld2" : "false" ,
    "nullFeld" : "null" ,
    "arrayFeld1" : [ 1 , 2 , 3 , 4 ] ,
    "arrayFeld2" : [ "a" , "b" , "c" ] ,
    "arrayObject" : [ {
      "textFeld" : "Wert" ,
      "zahlenFeld" : 2
      } ]
  },
  {
    "textFeld" : "zweiterWert" ,
    "zahlenFeld1" : 3 ,
    "zahlenFeld2" : 45.678 ,
    "booleanFeld1" : "false" ,
    "booleanFeld2" : "true" ,
    "nullFeld" : "null" ,
    "arrayFeld1" : [ 5 , 6 , 7 , 8 ] ,
    "arrayFeld2" : [ "d" , "e" , "f" ] ,
    "arrayObject" : [ {
      "textFeld" : "Wert2" ,
      "zahlenFeld" : 22
      } ]
  }
  ]

}


Am Ende des blauen Blocks könnte durch ein Komma getrennt das Name:Wert Paar für "varianteZwei" folgen. Bei genauerer Betrachtung haben wir eigentlich nur ein 'größeres' Array Objekt erstellt wie es bereits beim Feld "arrayObjekt" zum Einsatz kam.


Ob wir es mit solchen JSON Collections zu tun bekommen hängt natürlich vom zu kontaktierenden Webservice ab. Aber wer weiß wann wir so etwas selbst bereitstellen müssen. Die erweiterte Version hat auf jeden Fall den Charme, dass sie problemlos um weitere Varianten ergänzt werden kann.
 




Links zu den restlichen Kapiteln:

Einführung / Introduction 

Teil 1: Abkürzungen und was sie bedeuten
           / Abbreviations and their meaning

Teil 2: Wer ReST sagt, sagt auch JSON
          / In for a ReST, in for a JSON

Teil 3: Leerzeichen und andere Entitäten
          / BLANKS and other entities

Teil 4: JSON und der goldene Konverter
          / JSON and the golden converter

Teil 5: Die Startvorbereitungen
          / preparations for launch

Teil 6: Kleine Denkpause gefällig?
          / in need of a reflection period?

Teil 7: Fertig machen zur Landung
          / preparing for landing

Keine Kommentare:

Kommentar veröffentlichen