Anomalie der Corona SDK json-Bibliothek

Hallo an alle. Es ist für niemanden ein Geheimnis, dass die Verwendung von json in Ihren Projekten im Corona SDK einige Dinge recht bequem machen kann. Ich fand eine interessante Anomalie bei der Arbeit mit der Bibliothek, die sich in der Praxis als kein Fehler herausgestellt hat, sondern eine Funktion, die Sie kennen und auf die Sie vorbereitet sein sollten. Lassen Sie uns alles im Detail betrachten.

1. Beschreibung des Problems


Angenommen, wir haben ein Lua-Array, das so aussieht:

ar = {23,45,56,'weer'} 

Wenn Sie alles normale mit einem Verständnis der Sprache haben, wird Ihnen dieses Array wie unten gezeigt präsentiert, nur aufgrund der Umstände fettarm - SO MÖGLICH:

 ar = {[1] = 23,[2] = 45,[3] = 56,[4] = 'weer'} 

Wenn Sie sich entscheiden, dieses Array in json zu konvertieren, erhalten Sie über die Ausgabe Folgendes (natürlich vergessen wir nicht, die json-Bibliothek anzuschließen):

 ar = {[1] = 23,[2] = 45,[3] = 56,[4] = 'weer'} json = require "json" local str = json.encode(ar) print(str)--> [23,45,56,"weer"] 

Wie Sie sehen können, weiß json auch über die Existenz dieser Art von vereinfachtem Datensatz Bescheid, bei dem die Elemente des Arrays, wenn sie fortlaufend angeordnet werden, nicht explizit nummeriert werden. Dies ist wunderbar, da wir json in unseren Projekten häufig für das Netzwerkprotokoll oder zum Speichern in einer Datei verwenden und die zusätzliche Größe vollständig ist wozu.

Versuchen wir nun, den Drain wieder in eine Lua-Tabelle umzuwandeln und seinen Inhalt anzuzeigen, wobei wir auf die Datentypen der Schlüssel achten:

 local str = '[23,45,56,"weer"]' local ar2 = json.decode(str) for k,v in pairs(ar2)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer ]] 

Wie Sie sehen können, ist das Ergebnis mehr als erwartet, die Tabelle ar am Eingang entspricht vollständig der Tabelle ar2 am Ausgang. Nachdem wir nun den vorherigen 2 Punkten gefolgt sind, aber gleichzeitig ein Array vorhanden ist, in dem sich eine unterbrochene Sequenz im Array befindet, fügen wir den Schlüssel 6 (unter Umgehung von 5) mit dem Wert 'wtf' hinzu. Wir brechen.

 json = require "json" ar = {23,45,56,'weer',[6] = 'wtf'} local str = json.encode(ar) print(str)-->[23,45,56,"weer",null,"wtf"] local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer 6 number wtf ]] 

Wie Sie sehen können, hat sich alles wieder als großartig erwiesen, da json.encode diesen Fang erwartet hat und anstelle eines nicht vorhandenen 5-Schlüssels null eingefügt wurde und dies alles mit Erfolg endete. Wir werden hier nicht aufhören und dem Array einen weiteren 777-Schlüssel mit dem Wert 1 hinzufügen, was wir höchstwahrscheinlich erwarten dass die Tabelle auf die gleiche Weise konvertiert wird und 770 null enthält - dies ist sicherlich nicht die beste Option, da sie viel mehr Platz beansprucht, aber es gibt einfach keine andere Möglichkeit in json, ein vollständiges Analogon dieser lua-Tabelle zu erstellen, da der Schlüssel nicht in json ist kann klar sein vlen als Zahl. Wir schauen uns an, was passiert ist.

 json = require "json" ar = {23,45,56,'weer',[6] = 'wtf',[777] = 1} local str = json.encode(ar) print(str)-->{"1":23,"2":45,"3":56,"4":"weer","6":"wtf","777":1} local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 string 23 777 string 1 3 string 56 2 string 45 4 string weer 6 string wtf ]] 

Wie Sie sehen können, ging der Encoder in die andere Richtung und konvertierte alle Schlüssel mit der Werttypnummer in eine Zeichenfolge. Es ist kein Geheimnis, dass eine solche Funktion zu Fehlern führen kann und wird (wenn Sie nichts davon wissen) oder zu Krücken, die bei der Arbeit mit dieser Tabelle explizite Tonumber / Tstring-Transformationen verwenden. Dies wird auf keinen Fall viel Freude bereiten. Überlegen Sie, wie Sie damit umgehen sollen.

2. das Problem lösen


Um dieses Problem zu lösen, können Sie eine Funktion schreiben, die alle Arrays initialisiert, in denen das Problem aufgetreten ist. Dann müssen Sie sich im Code ständig an dieses Problem erinnern und diese Funktion überall anwenden. Dies ist ein normaler Weg, aber nicht der beste, und daher gibt es Plan B. Definieren Sie die Implementierung der Funktion json.decode neu, sodass alle Problembereiche automatisch konvertiert werden. Diese Lösung funktioniert sowohl beim ersten Verschachteln im übergebenen Array als auch bei tieferen Anhängen. Wir werden den Funktionswert direkt nach dem Verbinden der json-Bibliothek mit dem Projekt neu definieren. Die folgende Implementierung ist verfügbar:

 json = require "json" local jd = json.decode--   local norm_ar json.decode = function(ar,not_convert)--  local res = jd(ar) --     --    norm_ar = function(root) local res = {} --  for k,v in pairs(root)do res[k] = v end --   for k,v in pairs(res) do if type(k) == 'string' and--  string.match(tostring(k),'%D') == nil then--    -- string -> number root[tonumber(k)] = root[k] root[k] = nil--   end --      if type(v) == 'table' then norm_ar(v) end end return root end --   not_convert    return not_convert and res or norm_ar(res) end 

Versuchen Sie nun erneut, den vorherigen Vorgang auszuführen:

 ar = {23,45,56,'weer',[6] = 'wtf',[777] = 1} local str = json.encode(ar) print(str)-->{"1":23,"2":45,"3":56,"4":"weer","6":"wtf","777":1} local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer 6 number wtf 777 number 1 --]] 

Wie Sie sehen können, hat alles funktioniert und das Array hat seine frühere Struktur beibehalten. Zuletzt möchte ich hinzufügen, dass die neue Implementierungsoption json.decode einen zweiten optionalen Parameter unterstützt, der die Konvertierung deaktiviert, wenn Sie diese Konvertierung aus irgendeinem Grund vermeiden müssen.

Tschüss alle!

Source: https://habr.com/ru/post/de422591/


All Articles