Ein schnelles und speicherisches JSON-Objektmodell mit Unterstützung für effizientes Parsen und Schreiben im JSON-konformen Format.
Diese Bibliothek hängt nur vom Neslib -Repository ab. Es ist mit diesem Repository als Submodul enthalten.
Der Haupteintrittspunkt dieser Bibliothek ist die IJsonDocument -Schnittstelle. Es wird zum Parsen, Laden und Speichern von JSON -Dokumenten verwendet und bietet Zugriff auf das JSON -Objektmodell. Sie können eine JSON -Zeichenfolge wie folgt analysieren:
var
Doc: IJsonDocument;
begin
Doc := TJsonDocument.Parse( ' { "Answer" : 42 } ' );
end ;Beachten Sie, dass diese Bibliothek im Gegensatz zur offiziellen JSON-Spezifikation keine Zitate rund um Wörterbuchschlüssel erfordert (solange der Schlüssel keine Räume oder andere Nicht-Identifizierer-Zeichen enthält). Das Folgende ist also auch gültig:
Doc := TJsonDocument.Parse( ' { Answer : 42 } ' ); Sie können auch die Load verwenden, um aus einer Datei oder einem Stream zu laden.
Auf der Ausgabeseite verwenden Sie Save , um in einer Datei oder einem Stream zu speichern, oder ToJson um in eine JSON -Zeichenfolge auszugeben.
Sie können auch neue JSON -Dokumente von Grund auf neu erstellen, indem Sie mit den Methoden von CreateArray oder CreateDictionary von Grund auf neu sind:
var
Doc: IJsonDocument;
begin
Doc := TJsonDocument.CreateArray;
Doc.Root.Add( 42 );
end ;Wie Sie in diesem Beispiel sehen können, greifen Sie über die Root -Eigenschaft auf das JSON -Dokumentobjektmodell zu.
Im Zentrum des JSON -Objektmodells befindet sich der TJsonValue -Typ. Dies ist ein Datensatz, der jede Art von JSON -Wert aufnehmen kann.
Es bietet verschiedene implizite Conversion -Operatoren, um einen TJsonValue in einen anderen (Delphi) Typ zu konvertieren. Darüber hinaus gibt es verschiedene To* Methoden, die versuchen, einen TJsonValue zu konvertieren, aber einen bereitgestellten Standardwert zurückgeben, wenn die Konvertierung fehlschlägt.
Sie (können) niemals selbst TJsonValue erstellen; Die einzige Möglichkeit, einen TJsonValue zu erstellen, besteht darin, JSON -Array oder Wörterbuch einen Wert hinzuzufügen:
var
Doc: IJsonDocument;
begin
Doc := TJsonDocument.CreateArray;
Doc.Root.Add( 42 );
end ; Dieses Beispiel fügt einem JSON -Array einen TJsonValue (mit Wert 42) hinzu. Um ein neues Wörterbuch zu erstellen, verwenden Sie stattdessen die AddArray oder AddDictionary -Methoden:
var
Doc: IJsonDocument;
Dict: TJsonValue;
begin
Doc := TJsonDocument.CreateArray;
Dict := Doc.Root.AddDictionary;
Dict.AddOrSetValue( ' answer ' , 42 );
end ;Dies schafft ein neues Wörterbuch und fügt es dem Stammarray hinzu. Dann wird der Wert 42 zu diesem Wörterbuch unter dem Namen "Antwort" hinzugefügt.
Verwenden Sie, um den Typ eines Wertes zu überprüfen, die Eigenschaft TJsonValue.ValueType oder eine der TJsonValue.Is* -Methoden.
Wenn Sie versuchen, Methoden wie Add (oder AddOrSetValue ) für Werte zu verwenden, die keine Arrays (oder Wörterbücher) sind, wird eine Ausnahme angehoben.
Der Zugriff auf die Elemente in einem Array (unter Verwendung der Items -Eigenschaft) oder die Werte in einem Wörterbuch (unter Verwendung der Werte Values ) führt jedoch niemals zu einer Ausnahme, auch wenn der Array -Index nicht begrenzt ist. Dadurch können mehrere Array-/Wörterbuchzugriffe zusammengekettet werden, ohne die Gültigkeit jedes Zwischenschritts zu überprüfen. Zum Beispiel:
I := Doc.Root.Items[ 3 ].Values[ ' foo ' ].Values[ ' bar ' ].Items[ 4 ].ToInteger( 0 );Dies wird immer erfolgreich sein, aber es gibt 0 zurück, wenn einer der Zwischenwerte nicht verfügbar ist.
Die IJsonDocument -Schnittstelle erleichtert das Lesen und Schreiben von JSON in ein Dokumentobjektmodell.
Sie können jedoch auch das Lesen oder Schreiben von JSON manuell lesen oder schreiben, wenn Sie es vorziehen (z. B. um zu vermeiden, dass ein Objektmodell in den Speicher geladen werden muss). Sie können dies mit den Schnittstellen IJsonReader und IJsonWriter in der Einheit Neslib.Json.IO tun.
Diese Schnittstellen sind völlig unabhängig von einer DOM -Implementierung und erfordern nicht einmal die Neslib.Json -Einheit. Die Verwendung dieser Schnittstellen ist etwas komplizierter und erfordert jedoch etwas mehr Arbeit. Weitere Informationen finden Sie in der Einheit Neslib.Json.IO .
Es gibt auch eine XPath-ähnliche JSONPAD-Implementierung, die Sie zur Abfrage von JSON-Dokumenten verwenden können.
Es gibt keine offizielle JsonPath -Spezifikation, aber die am häufigsten verwendete Version scheint eine von Stefan Goessner entwickelt zu sein.
Ein JsonPath sieht aus wie:
$.store.book[0].titleoder
$['store']['book'][0]['title'] Beide Darstellungen sind identisch: Sie können entweder DOT- ( . ) Oder Klammer ( [] ) Notation verwenden, um Kinder eines Wörterbuchs zu bezeichnen. Klammern können auch mit numerischen Indizes verwendet werden, um Kinder eines Arrays per Index zu bezeichnen.
JsonPath verwendet nur einzelne Zitate (') in Klammern. Wir erlauben auch Doppelzitate ("), da diese in Delphi -Zeichenfolgen einfacher zu bedienen sind.
Zusamenfassend:
$ , das die Wurzel angibt, gefolgt von Null oder mehr Kinderbetreibern ( . Oder [] ). Ein $ von selbst entspricht dem gesamten Dokument.* oder '*' ) sein, die allen Kindern entspricht. Zum Beispiel entspricht $.store.book[*].author entspricht den Autoren aller Bücher im Laden.. ) Kann ein Doppelpunkt ( .. ) verwendet werden, um nach Nachkommen anstelle von unmittelbaren Kindern zu suchen. Zum Beispiel entspricht $..author entspricht allen Autoren, unabhängig von der Tiefe. Dies wird als rekursive Abstammung bezeichnet.$.store.book[0,2,3] den ersten, dritten und vierten Büchern.[Start:End:Step] verwenden, um einem Schicht (Bereich) von Kindern zu entsprechen. Dies entspricht allen Kindern, die vom Index Start (aber nicht einschließlich) End unter Verwendung einer bestimmten Step (normalerweise 1). Alle sind optional, aber mindestens ein Wert (und Dickdarm) muss angegeben werden:Start weggelassen wird, wird impliziert, dass ein negativer Wert vom Ende des Arrays einen Versatz angibt.End weggelassen wird, extrahiert die Scheibe durch das Ende des Arrays. Ein negativer Wert gibt vom Ende des Arrays angezeigt und ausgeglichen.Step weggelassen wird, ist IS impliziert 1.List[2:] entspricht dem dritten und allen folgenden Elementen.List[-2:] entspricht den letzten beiden Elementen.List[:2] entspricht den ersten beiden Elementen.List[:-2] entspricht allen bis auf die letzten beiden Elemente.List[2:-2] entspricht allen Elementen, aber den ersten zwei und den letzten beiden.List[-4:-2] entspricht den 3. und 4rd-Elementen vom Ende.List[::2] entspricht allen Elementen mit einem gleichmäßigen Index.JsonPath hat auch einen @ Operator, der benutzerdefinierte Skriptausdrücke zulässt. Wir unterstützen diesen Bediener nicht.
Beispieldokument:
{ "store" : {
"book" : [
{ "category" : " reference " ,
"author" : " Nigel Rees " ,
"title" : " Sayings of the Century " ,
"price" : 8.95
},
{ "category" : " fiction " ,
"author" : " J. R. R. Tolkien " ,
"title" : " The Lord of the Rings " ,
"isbn" : " 0-395-19395-8 " ,
"price" : 22.99
}
],
"bicycle" : {
"color" : " red " ,
"price" : 19.95
}
}
}Beispielpfade:
| Ausdruck | Ergebnis |
|---|---|
$ | Entspricht dem Stammdokument (ein einzelner Wert) |
$..* | Entspricht allen Mitgliedern im Dokument (viele Werte) |
$.store.book[*].author | Die Autoren aller Bücher im Laden |
$..author | Alle Autoren |
$.store.* | Alles auf Lager (2 Bücher und ein Fahrrad) |
$.store..price | Der Preis für alles im Laden |
$..book[2] | Das dritte Buch |
$..book[-1:] | Das letzte Buch in Ordnung |
$..book[:2] | Die ersten beiden Bücher |
Die JsonPath -API ist kurz und einfach. Es besteht aus einer TJsonPath -Aufzeichnung mit nur wenigen Methoden.
Verwenden Sie zur einmaligen Übereinstimmung die statische Match -Methode:
var
Doc: IJsonDocument;
Matches: TArray<TJsonValue>;
begin
Doc := TJsonDocument.Load(...);
Matches := TJsonPath.Match(Doc, ' $.store.book[*].author ' );
end ;Wenn Sie vorhaben, denselben Pfad in mehreren (Sub-) Dokumenten zu verwenden, ist es schneller, den Pfad einmal zu analysieren und ihn dann mehrmals anzuwenden:
var
Doc1, Doc2: IJsonDocument;
Path: TJsonPath;
Matches1, Matches2: TArray<TJsonValue>;
begin
Doc1 := TJsonDocument.Load(...);
Doc2 := TJsonDocument.Load(...);
Path := TJsonPath.Create( ' $.store.book[*].author ' );
Matches1 := Path.Match(Doc1);
Matches2 := Path.Match(Doc2);
end ;Sie können auch den Pfad auf Unterbäumen laufen:
var
Doc: IJsonDocument;
Store: TJsonValue;
Matches: TArray<TJsonValue>;
begin
Doc := TJsonDocument.Load(...);
Store := Doc.Root.Values[ ' store ' ];
Matches := TJsonPath.Match(Store, ' $.book[*].author ' );
end ; Wenn Sie nur an einem einzigen (oder ersten) Match interessiert sind, können Sie stattdessen MatchSingle verwenden:
var
Doc: IJsonDocument;
Match: TJsonValue;
begin
Doc := TJsonDocument.Load(...);
if (TJsonPath.MatchSingle(Store, ' $.book[*] ' , Match)) then
...
end ; Die gesamte Speicherverwaltung in dieser JSON -Bibliothek ist automatisch. Eine IJsonDocument -Schnittstelle besitzt alle TJsonValue und zerstört sie, wenn das Dokument zerstört wird (aus dem Spielraum herausgeht).
Das einzige, was Sie sich bewusst sein müssen, ist, dass Sie nach der Zerstörung des Dokuments keine TjsonValue -Datensätze mehr verwenden sollten. Dies führt zu undefiniertem Verhalten und möglicherweise zu Abstürzen.
Sie können ein gewisses Verhalten anhand dieser bedingten Defines anpassen:
JSON_UTF8 : Verwenden Sie UTF8String anstelle von String überall. Alle Saiten werden als 8-Bit-UTF-8-Saiten anstelle von 16-Bit-Unicode-Saiten behandelt. Dies reduziert den Speicherverbrauch und beschleunigt das Parsen ein wenig. Dies bedeutet jedoch, dass Sie diese JSON -Bibliothek auch mit UTF8Strings verwenden müssen, ansonsten wird Delphi implizit zwischen Unicode -Zeichenfolgen und UTF8strings konvertieren, was die Leistung beeinträchtigen kann.JSON_STRING_INTERNING : So aktivieren Sie die String -Einsprechung für Wörterbuchschlüssel. Dies reduziert den Speicherverbrauch, falls der gleiche Schlüssel vielmal verwendet wird (was häufig ist, wenn JSON aus einer Datenbank exportiert wird), ist jedoch etwas langsamer. Die neslib.json -Einheit deklariert den JsonString -Typ entweder als String oder UTF8String , abhängig von der Define JSON_UTF8 . Dies bedeutet jedoch nicht, dass Sie auch JsonString verwenden müssen. Wenn Sie sich nicht für die Definition JSON_UTF8 interessieren, können Sie mit dieser Bibliothek nur reguläre Zeichenfolgen verwenden.
Neslib.json ist unter der vereinfachten BSD -Lizenz lizenziert.
Einzelheiten siehe Lizenz.txt.