JSON

Hier lediglich ein knapper Überblick. Die genauen Details sind in RFC 4627 festgelegt.

Grundbausteine

Als atomare Grundbausteine, aus denen später komplexere Strukturen gebastelt werden können stellt das JSON-Format lediglich fünf Datentypen zur Verfügung, die sich in folgende drei Gruppen gliedern lassen:

Literale

Als Literal stehen folgende Werte zur Verfügung:

(!)

Groß-/Keinschreibung ist an dieser Stelle wichtig.

Alle genannten Literale null, true und false dürfen ausschließlich in Kleinbuchstaben geschrieben werden.

der Interesse bitte im Standard nachlesen. ||

Zahlen

Jede als Folge von Ziffern, optionalem Dezimalpunkt und optionalem Exponenten in "der üblicher Weise" darstellbare Zahl gilt auch im JSON Format als Zahl.

Auch hier einige Beispiele dazu:

   1 3.14159265
   2 42
   3 6.62606957e-34
   4 9.461E+15

Jedes der hier gelisteten Beispiele stellt eine gültige Zahl im JSON-Format dar.

{i}

Eine Angabe darüber welche Zahlenbreiche von einem JSON-Parser darstellbar sein müssen macht der Standard nicht.

Implementierungen ist es jedoch explizit erlaubt hier Einschränkungen zu machen.

Strings

Ein String muss dabei zwingend als eine Folge von Unicode-Zeichen kodiert werden, die zwischen doppelten Anführungszeichen " steht. Standard-Kodierungsformat ist hierbei UTF-8.

Hier ein kleines Beispiel dazu:

   1 "Gurkensalat"
   2 "φυσική"
   3 "hello world\n"
   4 "\"перестройка\""

Jedes der hier aufgelisteten Beispiele ist, sofern die einzelnen Zeichen korrekt kodiert sind ein gültiger JSON String.

(!)

Wie im vorletzten Beispiel angedeutet sind innerhalb eines Strings Escape-Sequenzen erlaubt.

Komplexere Strukturen

Zur Erstellung komplexerer Strukturen stellt das JSON Format zwei Möglichkeiten zur Verfügung:

Array

Zur Darstellung einer Liste von Werten ist es erlaubt die einzelnen Elemente einer Liste mit Komma , getrennt hintereinander zu schreiben und diese Auflistung in eckige Klammern [ und ] einzufassen.

Auch hier zunächst einige Beispiele:

   1 ["Hund", "Katze", "Maus"]
   2 [false, 3, "sieben", null, 9.81]
   3 [["liste 1", "e1"], ["liste 2", "e1", "e2"]]
   4 [ [[[]], []], [[[], []], []]]

Eine Einschränkung bezüglich der in einem Array enthaltenen Werte gibt es dabei, wie das zweites und drittes Beispiel demonstrieren nicht.

{i}

Wie beliebig ist beliebig?

Auch wenn er selbst keine Grenzen angibt erlaubt es der Standard Parser-Implementierungen ein Limit für die Verschachtelungstiefe zu setzen.

Objekt

Eine letzte Konstruktionsmöglichkeit fehlt schließlich noch um den JSON-Zoo komplett zu machen.

Hinter dem Namen Objekt verbirgt sich bei JSON nicht viel mehr als eine Abbildung von in Form eines JSON-Strings angegebenen namen auf zugehörige Werte. Name und Wert werden dabei durch einen Doppelpunkt :' voneinander getrennt und mehrere solcher Name-Wert Paare durch Komma , getrennt in geschweifte Klammern { und } eingefasst.

Hier die vorerst letzte Beispielrunde:

   1 { "name" : "Hase", "ahnung" : "keine", "lieblingszahl" : 23 }
   2 { "dreieck" : [[0,0], [2,0], [1,1]], "kreis" : { "zentrum" : [0,0], "radius": 3 }}
   3 { "Lieblingsfilme" : 
   4    [ { "Titel" : "Dr. Seltsam", 
   5        "Schauspieler" : ["Peter Sellers", "Sterling Hayden"] },
   6      { "Titel" : "Krieg der Sterne", 
   7 
   8        "Schauspieler" : "viel zu viele, um sie alle zu nennen"] }] } 

Wie zweites und drittes Beispiel zu demonstrieren versuchen darf auch hier wie bei der Konstruktion von Arrays beliebig eingeschachtelt, umschachtelt und verschachtelt werden.

Insbesondere ist es, wie im letzten Beispiel ebenso erlaubt Objekte innerhalb eines Arrays als Werte anzugeben.

{i}

Wie immer gibt der Standard auch hier kein prinizipielles Limit für die Verschachtelungstiefe vor.

Parser-Implementierungen dürfen aber auch hier Limits in nicht näher angegebenem Rahmen vorgeben.

Wie im letzten Beispiel ist es bei der Angabe eines Objektes, wie auch bei der Angabe eines Arrays nicht erforderlich alles in eine einzige Zeile zu verpacken. Stattdessen dürfen hierfür auch mehrere Zeilen verwendet werden.

{X}

ACHTUNG! Bei Import in MongoDB gilt die letzgemachte Angabe nicht.

Das Import-Werkzeug mongoimport erwartet hier stets ein vollständiges Objekt je Eingabezeile.

JSON-Text

Zu guter letzt bleibt nur noch zu klären wie genau denn nun ein gültiger JSON Text aus den genannten Komponenten konstruiert werden kann.

Ein JSON-Text darf wahlweise ein Array oder ein Objekt sein.


BSON

Sowohl intern, als auch für den Datenaustausch mit externen Werkzeugen verwendet die für den Erstimplementierungsversuch vorgesehene MongoDB das BSON-Format, dessen genauer Aufbau in der BSON-Spezifikation nachzulesen ist.

Dieses ermöglicht nicht nur eine Darstellung des Inhalts eines JSON-Dokuents in binärer Form, sondern kann zudem sogar noch ein wenig mehr.

{i}

Ohne dabei zu sehr vom Thema abzuschweifen hierzu lediglich folgende Kurzinfo

Zur Darstellung der Daten verwendet das BSON-Format ein klassisches TLV Kodierungsverfahren, das dafür interessanter Weise jedoch nicht wie eventuell erwartet in network byte order, sondern im little-endian Format erfolgt.

Eine Spezifikation des Formats findet sich unter folgendem link.

Da es das erklärte Ziel des Projektes für einen ersten Implementierungsversuch das JSON-Format als Austauschformat zu verwenden dürfte eine Vertiefung in die Erweiterungsmöglichkeiten des BSON-Formats allerdings nicht allzu viel nützliches zu Tage bringen.

Aus diesem Grund werden in diesem und in den folgenden Abschnitten vorerst nur diejenigen Bestandteile des BSON-Formats Erwähnung finden, für die es eine direkte Entsprechung im JSON-Format gibt.

Einschränkungen

Vorab hier noch einige wichtige Hinweise auf gewisse Einschränkung, die MongoDB bei der Datenmodelierung gerne eingehalten wissen möchte:

Umgang mit dem BSON-Format

Im folgenden die Auflistung einiger Besonderheiten, die bei Verwendung des BSON-Formates zu beachten sind:

{X}

ACHTUNG! Hierbei handelt es sich lediglich um den theretisch möglichen Maximalwert.

Die praktisch erreichbare Maximalgröße eines in der aktuellen Implementierung der MongoDB verwendbaren BBSON-Dokuments liegt lediglich bei 16 MB

Kodierung im BSON-Format

Bezüglich der Kodierung eines im BSON-Format darstellbaren JSON-Textes als BSON-Dokument sind weiter folgende Punkte zu beachten:

Grundbausteine

Komplexere Strukturen

Codeschnippsel

BSON und C

Im Lieferumfang des C-Treibers der MongoDB ist bereits eine Implementierung für die Bearbeitung im BSON-Format kodierter Daten enthalten. Dieser wird auf GitHub gehostet und findet sich unter folgendem link.

Die in den folgenden Abschnitten zusammengetragene Information soll einen kurzen Überblick über die API dieser Implementierung geben. Eine vollständige Dokumentation findet sich auf den Seiten des oben genannten C-Treibers. Erreichbar unter diesem link. Dort angekommen am besten gleich Mal unter API Docs nachschlagen, hier findet sich die vollständige Dokumentation.

BSON-Objekte

Der für die Repräsentation von BSON-Objekten vorgesehene Datentyp trägt den (hoffentlich) einfach zu merkenden Namen bson.

Werden keine Funktionen der MogoDB selbst benötigt, so sollte es genügen den Header "boson.h" einzubinden. Sollen zudem später auch der Funktionsumfang der MongoDB genutzt werden, so genügt Einbinden des Headers "mongo.h" dieser bindet oben genannten Header nämlich bereits selbst ein.

Workflow

In vereinfachter Übersicht geschieht die Arbeit mit einem BSON-Objekt nach folgendem Ablauf:

Erstellung:

Hiernach kann dann beliebig mit dem Objekt hantiert und gearbeitet werden.

Wird es dann schließlich nicht mehr gebraucht sollte der von der bson Library zur Darstellung des Objekts allozierte Speicherplatz dann auch wieder frei gegeben werden.

Vernichtung:

   1  #include <mongo.h>
   2 
   3  bson b;
   4  bson_init (&b); 
   5  //   BSON-Objekt mit Daten füllen 
   6  //   ...
   7  bson_finish (&b);
   8  //   mit dem BSON-Objekt arbeiten 
   9  //   ...
  10 
  11  bson_destroy (&b);

Ganz 'sauber' ist obiger Beispielcode noch nicht - wenigstens im Finalisierungsschritt (Aufruf der Funktion bson_finish()) sollte vor Verwendung getestet werden, ob bis dahin denn auch alles gut gegangen ist, bevor wie wild auf irgendwelchem Datenmüll operiert wird.

Gibt die Funktion bson_finalize() den Wert BSON_OK zurück, so ist alles gut verlaufen.

Befüllen

Glücklicherweise scheint das Befüllen eines BSON-Objekts nicht allzu kompliziert. Sämtliche Befüll-Funktionen folgen dabei nämlich mehr oder weniger dem selben Muster.

Jede Funktion trägt das Präfix bson_append_ gefolgt vom jeweils einzufügenden Datentyp. Als Parameter werden stets eine Referenz auf das zu bearbeitende Objekt, der für diesen Wert zu vergebende Name und falls nötig der zuzuweisende Wert erwartet.

Für die Grundbausteine ergibt sich somit folgende Übersicht:

JSON

BSON

null

bson_append_null

true

bson_append_bool

false

Zahl

bson_append_int

{i}

Die zur Verfügung stehenden Funktionen legen hier eine Zahl entsprechen den in Abschitt zur Kodierung im BSON-Format genannten Datentypen. int32 int64, bzw. double

bson_append_long

bson_append_double

String

bson_append_string

bson_append_string_n

{i}

der Parameter n gibt hier die Länge der Zeichenkette an

komplexere Strukturen

Zur Erstellung komplexerer Strukturen stehen die Funktionen 'bson_start_array' und 'bson_finish_array', bzw. 'bson_start_object' und 'bson_finish_object' zur Verfügung.

Auch hierzu ein kurzer Code-Schnippsel. Angelegt werden soll dabei ein BSON-Objekt das folgendem JSON-Text entspricht:

   1 {
   2   Name: "Familie Simpson", 
   3   Adresse : { Straße : "Evergreen Terrace", nr : 742 },
   4   Mitglieder : ["Homer", "Marge", "Bart", "Lisa", "Maggie" ]

Hier der zugehörige C-Code:

   1 #include <gtk/gtk.h>
   2 #include "mongo.h"
   3 
   4 int main (int argc, char *argv[]) {
   5 
   6     bson *b =  g_new (bson, 1);
   7     bson_init (b);
   8 
   9     bson_append_string (b, "Name", "Familie Simpson");
  10 
  11     bson_append_start_object (b, "Adresse");
  12     bson_append_string (b, "Straße", "Evergreen Terrace");
  13     bson_append_int (b, "nr", 742);
  14     bson_append_finish_object (b);
  15 
  16     bson_append_start_array (b, "Mitglieder");
  17     bson_append_string (b, "0", "Homer");
  18     bson_append_string (b, "1", "Marge");
  19     bson_append_string (b, "2", "Lisa");
  20     bson_append_string (b, "3", "Maggie");
  21     bson_append_finish_array (b);
  22 
  23     bson_finish(b);
  24     
  25     bson_print (b);
  26 
  27     bson_destroy (b);
  28     
  29     return 0;
  30 }

Iteratoren

Um nun wieder an die verpackten Daten heranzukommen werden Iteratoren vom Typ bson_iterator verwendet, mit denen ein BSON-Objekt durchwandert werden kann.

lugfrankfurt: Programmierworkshop/projekte/interlinearisator/formate (zuletzt geändert am 2012-08-04 23:54:55 durch Bernd)