Json.Luaの仕様確認
Json.Luaは、LuaでJsonが扱えるようになるライブラリです。ここにあります(多分)。
Jsonとは、環境や言語を超えてデータを受け渡しするために考案されたデータ記述形式です。同様の目的にxmlとそのサブセット群がありますが、xmlはパースの手間が面倒(時間がかかったりメモリを食ったり)だったりするので、プリミティブな変数への変換ができるJsonができました。そんな感じで聞いてます。
本来の目的は、Ajaxなどでサーバーとブラウザ間でのデータ交換に使われますが、それとは別に保存形式として使うこともできなくはありません。
使い方
dofile("json.lua")
これで準備オーケー。基本二つの関数を使う。
local variable = {} -- 適当な変数 local str = Json.Encode(variable) -- 変数を一つの文字列にしてしまう。 local variable = Json.Decode(str) -- Encodeで作った文字列を与えると、変数にして返す。
基本的な確認
local a = {} a[1+#a] = 100 a[1+#a] = "string" a[1+#a] = {} a[1+#a] = true io.open("json.txt", "w"):write(Json.Encode(a))
こうすると、json.txtの中身は、
[100,"string",[],true]
こうなる。
配列ではなくて、連想配列にしてみる。
local a = {} a["1"] = 100 a["2"] = "string" a["3"] = {} a["4"] = true io.open("json.txt", "w"):write(Json.Encode(a))
すると、こうなる。
{"1":100,"4":true,"3":[],"2":"string"}
混在させてみる。
local a = {} a[1] = 100 a[2] = "string" a["3"] = {} a["4"] = true io.open("json.txt", "w"):write(Json.Encode(a))
すると。
{"1":100,"2":"string","3":[],"4":true}
おお、なんたること、数値のキーが文字列に変換させられている!
これは注意が必要だ。配列なら配列、連想配列なら連想配列に限定した方がいいな。
その他の変数型を与えてみると?
ちなみにfunctionとかが含まれているとEncode時点でこける。使えるのは、number, string, boolean, tableの基本的なデータだけに限った方がよさそうだ。
間の開いた配列ならどうなるか。
local a = {} a[1] = 1 a[3] = 3 io.open("json.txt", "w"):write(Json.Encode(a))
こうなる。
[1,null,3]
ちゃんと間を開けてくれる。nilはnullになる。
循環参照を与えるとどうなるか。
local a = {} a[1] = {} a[1][1] = a io.open("json.txt", "w"):write(Json.Encode(a))
Encode時点で、Stack Overflowを出して止まる。
つまり、与えるなと言うことか。
メタテーブル持ちを与えてみる。
Luaでオブジェクト指向するのに必要なメタテーブル。それを設定したテーブルを与えるとどうなるか。
local mt = {__index=function(t, k) return 20 end} local a = {} a[1] = 30 a = setmetatable(a, mt) io.open("json.txt", "w"):write(Json.Encode(a))
結果。
[30]
消えちゃったー。そりゃそうか。
メタテーブルでいじった後のテーブルを与えるとどうなるか。
local mt = {__index=function(t, k) rawset(t, k, 20); return rawget(t, k) end} local a = {} a[1] = 30 a = setmetatable(a, mt) local dummy = a[2] io.open("json.txt", "w"):write(Json.Encode(a))
結果。
[30,20]
当然ながら、メタテーブルそのものは保存されなくても、メタテーブルによって作成されたデータは保存の対象になるようだ。