Json.Luaの仕様確認

Json.Luaは、LuaJsonが扱えるようになるライブラリです。ここにあります(多分)。
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"}

混在させてみる。

Luaでは、配列と連想配列をごっちゃにできる。

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]

当然ながら、メタテーブルそのものは保存されなくても、メタテーブルによって作成されたデータは保存の対象になるようだ。