JsonStore Module/de
From OpenSimulator
Languages: |
English Deutsch |
Einführung
Das JsonStore-Modul ermöglicht es Skripten und Region-Modulen, strukturierte Daten zu teilen. Bitte beachten Sie, dass es sich derzeit im experimentellen Stadium befindet und Änderungen unterliegen kann, die dazu führen können, dass ältere Skripte nicht mehr funktionieren oder leicht anders funktionieren.
Um JsonStore zu verwenden, wenn Sie OpenSimulator auf Mono ausführen, muss die Version von Mono höher als 2.8 sein (vorzugsweise mindestens in der 2.10er Reihe). Unter Windows ist JsonStore ab OpenSimulator 0.8.0 Dev Master bei r/24021 verfügbar (wenn das zugrunde liegende .NET von v3.5 auf v4 geändert wurde).
Knoten sind derzeit auf Array, Objekt und String beschränkt. Wenn JSON hinzugefügt wird (über JsonCreateStore(), JsonSetJson() oder andere solche Methoden), das rohe Zahlenwerte enthält, können diese dennoch abgerufen werden, aber nur als Strings.
Aktivierung des Moduls
Fügen Sie Folgendes zu Ihrer OpenSim.ini hinzu, um das JsonStore-Modul zu aktivieren:
[JsonStore] Enabled = true
Wenn Sie über Skriptmethoden auf JsonStore zugreifen möchten, müssen Sie auch die Berechtigung für MOD-Funktionen aktivieren, falls Sie dies noch nicht getan haben:
[XEngine] AllowMODFunctions = true
Allgemeine Punkte
- Das Modul funktioniert, indem es Skripten ermöglicht, ihre eigenen Stores für JSON-Daten zu erstellen. JSON kann entweder direkt geschrieben, von einer Notizkarte gelesen oder auf andere Weise hinzugefügt werden (z. B. durch eine separate Anfrage, um Daten von einem externen Server abzurufen).
- Stores werden über einen Schlüssel referenziert. Dieser Schlüssel kann an andere Skripte weitergegeben werden, sodass sie denselben Store teilen können.
- Stores werden nicht gespeichert. Sobald der Simulator zurückgesetzt wird, verschwinden die Daten, wenn keine weiteren Schritte unternommen werden, um sie zu speichern (z. B. in Notizkarten).
- Wenn Sie mit einem Store fertig sind, sollten Sie ihn mit der Funktion JsonDestroyStore() entfernen. Stores, die von einem Skript erstellt wurden, werden jedoch beim Löschen oder Zurücksetzen des Skripts vom Garbage Collector entfernt. Dies kann andere Skripte beeinträchtigen, wenn sie Zugriff auf einen freigegebenen Store haben.
- Wenn Sie den gesamten Inhalt eines Stores zu Debugging-Zwecken über ein Skript anzeigen möchten, ist eine gute Möglichkeit, dies zu tun, das serialisierte JsonStore mit der Skriptzeile auszugeben
llOwnerSay(JsonGetJson(storeID, "."));
JsonStore-Pfadsyntax
Ein JsonStore-Pfad ist eine durch '.' getrennte Zeichenkette von Tokens, die Elemente des Json-Stores referenzieren. Pfad-Tokens sind entweder Strings (für den Strukturzugriff) oder Array-Referenzen. Das '+'-Token bezieht sich auf das Ende des Arrays und wird verwendet, um Werte an ein Array anzuhängen. Strings werden mit den Zeichen "{" und "}" zitiert. Array-Referenzen werden mit "[" und "]" zitiert. Wenn keine Mehrdeutigkeit besteht, kann der '.'-Separator weggelassen werden.
Die Funktion JsonList2Path kann verwendet werden, um eine Liste von Tokens in einen JsonStore-Pfad zu konvertieren. Dies ist besonders nützlich, wenn Sie durch Arrays im Store iterieren möchten.
Formale Syntax
Path --> Token | Path '.' Token Token --> '[' Index ']' | '{' Identifier '}' | SimpleIdentifier Index --> '+' | [0-9]+ Identifier --> [^}]+ SimpleIdentifier --> [a-zA-Z]+
Beispiele
// Referenzieren des Wurzelknotens, wie in Aufrufen wie JsonGetJson(storeId, ".") // um den gesamten Store zu serialisieren "." // Referenzieren eines Elements "elem" // Referenzieren eines Array-Elements "[0]" // Referenzieren eines Array-Elements, bei dem elem der Schlüssel ist. Dies ist eine Abkürzung für elem.[0] "elem[0]" // Referenzieren eines Array-Elements, bei dem elem der Schlüssel ist. "elem.[0]" // Referenzieren eines Array-Elements, bei dem elem der Schlüssel ist und elem selbst // Klammern {}, eckige Klammern [] oder Punkte . enthält "{elem}.[0]" // Dies ist ein Pfad mit zwei Tokens, mit dem Bezeichner "foo.bar" und der Array-Referenz "0" "{foo.bar}.[0]" // Dies ist ein Pfad mit zwei Tokens, mit dem Bezeichner "foo.bar" und der Array-Referenz "0" // und foo oder bar enthalten Elemente, die abgegrenzt werden müssen. "{foo}.{bar}.[0]" // Dies ist ein Pfad mit vier Tokens: [{foo}, {bar}, [0], {goof}] "foo.bar[0].goof"
JsonStore-Wertschnittstelle
JsonStore-Region-Modul-API
Methoden zur Manipulation des Regionsspeichers sind über die IJsonStore-Schnittstelle im Interfaces-Verzeichnis von OpenSim.Region.Framework.dll zugänglich.
Diese Methoden sind:
public delegate void TakeValueCallback(string s); public enum JsonStoreNodeType { Undefined = 0, Object = 1, Array = 2, Value = 3 } public enum JsonStoreValueType { Undefined = 0, Boolean = 1, Integer = 2, Float = 3, String = 4, UUID = 5 } public interface IJsonStoreModule { bool AttachObjectStore(UUID objectID); bool CreateStore(string value, ref UUID result); bool DestroyStore(UUID storeID); JsonStoreNodeType GetNodeType(UUID storeID, string path); JsonStoreValueType GetValueType(UUID storeID, string path); bool TestStore(UUID storeID); bool SetValue(UUID storeID, string path, string value, bool useJson); bool RemoveValue(UUID storeID, string path); bool GetValue(UUID storeID, string path, bool useJson, out string value); void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); int GetArrayLength(UUID storeID, string path); }
TODO: Dokumentation zu diesen Methoden. An diesem Punkt müssen Sie sich auf die untenstehenden vergleichbaren Skriptfunktionen beziehen.
JsonStore-Skriptfunktionen
Konstanten
Das JsonStore-Modul bietet Funktionen zur Abfrage des Speichers, um Knoten- und Werttypen zu testen. Die folgenden Konstanten werden von der JsonGetNodeType-Funktion zurückgegeben:
- JSON_NODETYPE_UNDEF - der Knotentyp ist unbekannt oder der Knoten existiert nicht
- JSON_NODETYPE_OBJECT - der Knoten ist ein schlüsselzugreifendes Wörterbuch
- JSON_NODETYPE_ARRAY - der Knoten ist ein indexzugreifendes Array
- JSON_NODETYPE_VALUE - der Knoten ist ein Wert
Und die folgenden Konstanten beschreiben die Werttypen eines JSON_NODETYPE_VALUE-Knotens:
- JSON_VALUETYPE_UNDEF - der Wert ist unbekannt oder der Knoten ist kein Wert
- JSON_VALUETYPE_BOOLEAN - der Wert des Knotens ist ein boolescher Wert
- JSON_VALUETYPE_INTEGER - der Knoten hat einen ganzzahligen Wert
- JSON_VALUETYPE_FLOAT - der Knoten hat einen Fließkommawert
- JSON_VALUETYPE_STRING - der Knoten hat einen Zeichenfolgenwert
Beachten Sie, dass alle Zugriffsmethoden auf einem JsonStore derzeit eine Zeichenfolge zurückgeben, die in einen anderen Wertetyp umgewandelt werden kann.
Grundfunktionen
Diese Funktionen ermöglichen es Ihnen, Speicher zu manipulieren, Werte zu setzen, zu erhalten und zu testen sowie JSON auf Notizkarten zu lesen und zu schreiben.
- JsonCreateStore
- JsonAttachObjectStore
- JsonDestroyStore
- JsonTestStore
- JsonRezAtRoot
- JsonReadNotecard
- JsonWriteNotecard
- JsonList2Path
- JsonGetNodeType/JsonGetValueType
- JsonGetValue/JsonGetJson
- JsonSetValue/JsonSetJson
- JsonRemoveValue
- JsonGetArrayLength
- JsonTakeValue/JsonTakeJson
- JsonReadValue/JsonReadJson
Schlüssel storeID = JsonCreateStore(string jsonvalue)
Erstellen Sie einen JsonStore und initialisieren Sie ihn mit dem Json-codierten Wert. Der neue Speicherbezeichner wird zurückgegeben.
// Erstellen Sie einen JsonStore, der mit einem Schlüssel 'Hello' initialisiert wird, // der auf die Zeichenfolge 'World' zeigt, und einem Schlüssel 'Event', der auf ein Array mit zwei Werten '1, 2' zeigt. default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); JsonDestroyStore(storeID); } }
integer status = JsonAttachObjectStore()
Stellen Sie sicher, dass ein Store mit dem Objekt verknüpft ist (erstellt den Store, falls er noch nicht existiert). Der Store-Bezeichner ist derselbe wie der Objekt-Bezeichner, in dem das Skript ausgeführt wird.
integer status = JsonDestroyStore(key storeID)
Zerstören Sie den JsonStore, der mit dem angegebenen Bezeichner verknüpft ist. Sie sollten dies aufrufen, wenn Sie mit einem JsonStore fertig sind.
Gibt 1 zurück, wenn die Operation erfolgreich war. Gibt 0 zurück, wenn die Operation nicht erfolgreich war oder der Store nicht existiert.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); integer res = JsonDestroyStore(storeID); llOwnerSay("Ergebnis " + (string)res); JsonDestroyStore(storeID); } }
integer status = JsonTestStore(key storeID)
Gibt 1 zurück, wenn der angegebene Store existiert, oder 0, wenn er nicht existiert. Wird verwendet, um zu testen, ob ein freigegebener Store erstellt wurde.
key requestID = JsonWriteNotecard(key storeID, string path, string notecard)
Fordern Sie an, dass der durch den angegebenen Pfad identifizierte Wert Json-kodiert und in die Notizkarte geschrieben wird. Die Funktion gibt den Anforderungsbezeichner zurück. Wenn die Operation abgeschlossen ist, wird ein link_message-Ereignis mit dem Anforderungsbezeichner generiert.
key requestID; key storeID; default { touch_start(integer n) { storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); requestID = JsonWriteNotecard(storeID, "", "nc1"); } link_message(integer sender, integer ival, string sval, key id) { if (sender != -1) return; if (id == requestID) { llOwnerSay("Notizkarte geschrieben"); JsonDestroyStore(storeID); } } }
key requestID = JsonReadNotecard(key storeID, string path, key assetID)
Fordern Sie an, dass der Json-kodierte Inhalt einer Notizkarte dekodiert und an der angegebenen Pfadstruktur im Store platziert wird. Die Funktion gibt den Anforderungsbezeichner zurück. Wenn die Operation abgeschlossen ist, wird ein link_message-Ereignis mit dem Anforderungsbezeichner generiert.
Dieses Beispiel geht davon aus, dass das Prim die "nc1"-Notizkarte enthält, die im Beispiel JsonWriteNotecard() gespeichert ist.
key requestID; key storeID; default { touch_start(integer n) { storeID = JsonCreateStore("{}"); requestID = JsonReadNotecard(storeID, "", "nc1"); } link_message(integer sender, integer ival, string sval, key id) { if (sender != -1) return; if (id == requestID) { llOwnerSay("Notizkarte gelesen: " + JsonGetValue(storeID,"Event[0]")); JsonDestroyStore(storeID); } } }
key requestID = JsonRezAtRoot(string item, vector pos, vector velocity, rotation rot, string param)
Diese Funktion ist sehr ähnlich wie llRezAtRoot, mit zwei Unterschieden. Der erste ist, dass die Zeichenfolge "param" als JSON analysiert und in einem Speicher gespeichert wird, der durch den neu erstellten Objektbezeichner identifiziert wird. Der zweite Unterschied besteht darin, dass für jedes der erstellten Objekte ein link_message-Ereignis generiert wird. Der ganzzahlige Parameter ist die Anzahl der noch zu erstellenden Objekte (für koaleszierte Objekte), der string Parameter ist der Bezeichner des neu erstellten Objekts und der key Parameter ist der Anforderungsbezeichner, der durch den Aufruf von JsonRezAtRoot zurückgegeben wird.
key requestID; default { touch_start(integer i) { // Rez das Objekt "reztest" aus dem aktuellen Objektinventar, gebe ihm das JSON // Fragment "{ 'start' : 'abc' }" als Startparameter in seinem Objektspeicher string sparam = "{ 'start' : 'abc' }"; requestID = JsonRezAtRoot("Object", llGetPos() + <0.0, 0.0, 5.0>, ZERO_VECTOR, llGetRot(), sparam); } link_message(integer sender, integer result, string msg, key id) { if (sender != -1) return; if (id == requestID) llOwnerSay("Objekt erstellt " + msg); } }
Und das neue Objekt könnte den folgenden Code verwenden, um den Wert aus dem Objektspeicher zu extrahieren:
default { state_entry() { if (JsonTestStore(llGetKey())) { llOwnerSay("Lese Startparameter aus dem Objektspeicher"); llOwnerSay("Startparameter sind " + JsonGetJson(llGetKey(), ".")); } } on_rez(integer p) { llResetScript(); } }
string value = JsonGetValue(key storeID, string path)
Gibt den durch den Pfad identifizierten Wert zurück. Im Falle von JsonGetValue() muss der Wert eine Zeichenfolge sein. Wenn der Wert existiert, wird er zurückgegeben. Wenn der Wert nicht existiert oder der Speicher nicht existiert, wird eine leere Zeichenfolge zurückgegeben.
Die rohe Zeichenfolge wird zurückgegeben. Wenn Sie ein Zeichenfolgen-Token möchten, das Sie dann mit JsonSetValueJson() verwenden können, müssen Sie JsonGetValueJson() verwenden.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : { 'World' : 'Today' } }"); string res = JsonGetValue(storeID, "Hello.World"); llOwnerSay("Ergebnis " + res); // res wird Today sein JsonDestroyStore(storeID); } }
string jsonvalue = JsonGetJson(key storeID, string path)
Gibt den durch den Pfad identifizierten Wert zurück. Im Falle von JsonGetJson() wird der Wert eine Json-kodierte Zeichenfolge, ein Array oder ein Wörterbuch sein. Wenn der Wert nicht existiert oder der Speicher nicht existiert, wird eine leere Zeichenfolge zurückgegeben.
Bitte beachten Sie, dass, wenn der Wert eine Zeichenfolge ist (d. h. ein Blattknoten), er als Token zurückgegeben wird, das von einfachen Anführungszeichen (') umgeben ist, anstatt als rohe Zeichenfolge. Dies kann dann in JsonSetJson() verwendet werden.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : { 'World' : 'Today' } }"); string res = JsonGetJson(storeID, "Hello"); llOwnerSay("Ergebnis " + res); JsonDestroyStore(storeID); } }
integer status = JsonSetValue(key storeID, string path, string value)
Speichert den Wert an der durch den Pfad im Speicher identifizierten Stelle. Jeder Wert, der sich derzeit an dieser Stelle befindet, wird ersetzt. JsonSetValue() geht davon aus, dass der Wert eine Zeichenfolge ist.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); integer intRes = JsonSetValue(storeID, "Pancake.Banana", "Apple"); llOwnerSay("Set-Ergebnis " + (string)intRes); string stringRes = JsonGetValue(storeID, "Pancake.Banana"); llOwnerSay("Get-Ergebnis " + stringRes); JsonDestroyStore(storeID); } }
integer status = JsonSetJson(key storeID, string path, string jsonvalue)
Speichern Sie das JSON an der durch den Pfad im Store identifizierten Stelle. Alle derzeit an dieser Stelle vorhandenen Daten werden ersetzt. Der angegebene Wert muss eine JSON-kodierte Zeichenfolge sein. Wenn Sie einen Zeichenfolgen-Blattknoten angeben möchten, muss dieser von einfachen Anführungszeichen (') umgeben sein.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : 'World'}"); integer intRes = JsonSetValue(storeID, "Hello.World", "'Apple'"); llOwnerSay("Set result " + (string)intRes); string stringRes = JsonGetValue(storeID, "Hello.World"); // returns Apple llOwnerSay("Get result " + stringRes); intRes = JsonSetJson(storeID, ".", "{'Event' : ['1', '2']}"); llOwnerSay("Set result " + (string)intRes); string stringRes = JsonGetValue(storeID, "Event[0]"); // returns 1 llOwnerSay("Get result " + stringRes); JsonDestroyStore(storeID); } }
integer status = JsonRemoveValue(key storeID, string path)
Entfernen Sie den durch den Pfad identifizierten Wert aus dem Store.
(In OpenSimulator 0.7.5). Gibt 1 zurück, wenn der Wert entfernt wurde oder der Wert nicht existierte. Gibt 0 zurück, wenn der Store nicht existiert.
(In der nächsten Veröffentlichung). Gibt 1 zurück, wenn der Wert entfernt wurde. Gibt 0 zurück, wenn der Pfad nicht existiert oder der Store nicht existiert.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); integer intRes = JsonRemoveValue(storeID, "Hello"); llOwnerSay("Remove result " + (string)intRes); intRes = JsonTestPath(storeID, "Hello"); llOwnerSay("TestPath result " + (string)intRes); JsonDestroyStore(storeID); } }
integer res = JsonGetArrayLength(key storeID, string path)
Nur aktueller Entwicklungscode (wird in OpenSimulator 0.7.6 veröffentlicht).
Erhalten Sie die Länge des Arrays am angegebenen Pfad. Gibt -1 zurück, wenn
- Der Pfad nicht existiert
- Der Knoten am Pfad kein Array ist
- Der JsonStore für den storeID nicht existiert.
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : { 'World' : ['1', '2'] } }"); integer res = JsonGetArrayLength(storeID, "Hello.World"); llOwnerSay("Ergebnis " + (integer)res); // sollte 2 sein JsonDestroyStore(storeID); } }
Hilfsfunktionen
Dies sind Funktionen, die beim Manipulieren von JSON oder der Verwendung des Stores helfen.
- JsonList2Path
- JsonGetNodeType
- JsonGetValueType
string path = JsonList2Path(list components)
Konvertieren Sie die angegebene Liste von Komponenten in einen Pfad. Komponenten können Zeichenfolgen oder Ganzzahlen sein. Zeichenfolgen werden als normale Pfadnamenskomponenten verwendet. Ganzzahlen werden als Indexkomponenten zu Arrays verwendet.
Diese Methode existiert hauptsächlich, um das Iterieren durch Arrays zu erleichtern.
Zum Beispiel:
default { touch_start(integer n) { key storeID = JsonCreateStore("{'Hello' : {'World' : [{'name' : 'pete'}, {'name' : 'tom'}, {'name' : 'wilma'}]}}"); integer i; string path; string name; for (i = 0; i < JsonGetArrayLength(storeID, "Hello.World"); i++) { path = JsonList2Path(["Hello.World", i, "name"]); name = JsonGetValue(storeID, path); llOwnerSay(path + " ist '" + name + "'"); } JsonDestroyStore(storeID); } }
int nodetype = JsonGetNodeType(key storeid, string path)
Gibt den Typ des Knotens zurück, der durch den angegebenen Pfad identifiziert wird. Die folgenden Knotentypen können zurückgegeben werden:
- JSON_NODETYPE_UNDEF - der Knotentyp ist unbekannt oder der Knoten existiert nicht
- JSON_NODETYPE_OBJECT - der Knoten ist ein schlüsselzugreifendes Wörterbuch
- JSON_NODETYPE_ARRAY - der Knoten ist ein indexzugreifendes Array
- JSON_NODETYPE_VALUE - der Knoten ist ein Wert
int valuetype = JsonGetValueType(key storeid, string path)
Für Knoten im Speicher, die Werte angeben, wird der gespeicherte Wertetyp zurückgegeben. Beachten Sie, dass derzeit nur Zeichenfolgenwerte über die JsonGetValue- und JsonSetValue-Skriptfunktionen gesetzt oder zurückgegeben werden können. Andere Werte können jedoch in JSON-Fragmenten in Notizkarten oder mithilfe der JsonSetJson- oder JsonGetJson-Funktionen angegeben werden.
Die folgenden Wertetypen können zurückgegeben werden:
- JSON_VALUETYPE_UNDEF - der Wert ist unbekannt oder der Knoten ist kein Wert
- JSON_VALUETYPE_BOOLEAN - der Wert des Knotens ist ein Boolescher Wert
- JSON_VALUETYPE_INTEGER - der Knoten hat einen ganzzahligen Wert
- JSON_VALUETYPE_FLOAT - der Knoten hat einen Fließkommawert
- JSON_VALUETYPE_STRING - der Knoten hat einen Zeichenfolgenwert
Erweiterte Funktionen
Dies sind Funktionen, die es Skripten ermöglichen, Benachrichtigungen über Werte zu erhalten, wenn sie verfügbar werden. Dies ist nützlich für die Signalübertragung zwischen Skripten oder zwischen Skripten und Regionsmodulen.
- JsonTakeValue/JsonTakeValueJson
- JsonReadValue/JsonReadValueJson
key requestID = JsonTakeValue(key storeID, string path)
key requestID = JsonTakeValueJson(key storeID, string path)
Fordern Sie an, dass der durch den Pfad identifizierte Wert aus dem Store entfernt und an das Skript zurückgegeben wird, wenn er verfügbar ist. Der Wert wird über ein link_message-Ereignis mit der requestID zurückgegeben. JsonTakeValue() fordert einen Zeichenfolgenwert an. JsonTakeValueJson() fordert eine JSON-kodierte Zeichenfolge an, die einer Zeichenfolge, einem Array oder einem Hash-Wert entspricht.
Diese Funktion wird verwendet, um auf einen verfügbaren Wert zu warten und dann zurückzukehren. Da die Operation von Lesen und Entfernen atomar ist, kann sie verwendet werden, um Sperren, Aufgabenwarteschlangen und andere Synchronisationsprimitive zu implementieren.
key requestID; key storeID; default { state_entry() { storeID = JsonCreateStore("{'Hello' : 'World', 'Event' : ['1', '2']}"); JsonWriteNotecard(storeID, "", "nc1"); } touch_start(integer n) { requestID = JsonReadNotecard(storeID, "", "nc1"); } link_message(integer sender, integer ival, string sval, key id) { if (sender != -1) return; if (id == requestID) { llOwnerSay("Notizkarte gelesen: " + JsonGetValue(storeID, "Event[0]")); JsonDestroyStore(storeID); } } }
key requestID = JsonReadValue(key storeID, string path)
key requestID = JsonReadValueJson(key storeID, string path)
Fordern Sie an, dass der durch den Pfad identifizierte Wert an das Skript zurückgegeben wird, wenn er verfügbar ist. Der Wert wird über ein link_message-Ereignis mit der requestID zurückgegeben. JsonReadValue() fordert einen Zeichenfolgenwert an. JsonReadValueJson() fordert eine JSON-kodierte Zeichenfolge an, die einer Zeichenfolge, einem Array oder einem Hash-Wert entspricht.
Im Gegensatz zur JsonTakeValue()-Operation entfernt die JsonReadValue-Operation den Wert nicht aus dem Store, sobald er verfügbar wird.