Serialization and Data Files
Prerequisites: Files and I/O, Iterators
Lua as a data format
Lua's table constructors make a great data format: a data file can simply be Lua code that returns a table.
local function serialize(value, indent)
indent = indent or ""
local t = type(value)
if t == "number" or t == "boolean" or t == "nil" then
return tostring(value)
elseif t == "string" then
return string.format("%q", value)
elseif t == "table" then
local keys = {}
for k in pairs(value) do keys[#keys + 1] = k end
table.sort(keys, function(a, b) return tostring(a) < tostring(b) end)
local lines = {}
local inner = indent .. " "
for _, k in ipairs(keys) do
local key = type(k) == "string" and k:match("^[%a_][%w_]*$") and k
or "[" .. serialize(k) .. "]"
lines[#lines + 1] = inner .. key .. " = " .. serialize(value[k], inner)
end
return "{\n" .. table.concat(lines, ",\n") .. "\n" .. indent .. "}"
end
error("cannot serialize a " .. t)
end
local save = {player = "Ada", level = 3, items = {"sword", "key"}, alive = true}
local text = "return " .. serialize(save)
print(text)
local loaded = load(text)()
print(loaded.player, loaded.items[2], loaded.level)
return {
alive = true,
items = {
[1] = "sword",
[2] = "key"
},
level = 3,
player = "Ada"
}
Ada key 3
load(text) compiles a string of Lua code into a function; calling it
returns the table. Only load trusted data this way — a data file is
code, and could do anything (Level 3 shows how to load it in a sandbox).
JSON
Lua has no built-in JSON. Popular libraries:
-- illustrative
local json = require("dkjson") -- pure Lua: luarocks install dkjson
local text = json.encode({name = "Ada", tags = {"admin"}}, {indent = true})
local data = json.decode('{"name": "Linus", "langs": ["C", "Rust"]}')
print(data.langs[2]) --> Rust
- dkjson and rxi/json.lua — pure Lua, single-file.
- lua-cjson — fast C implementation (built into OpenResty).
- Neovim has
vim.json; LÖVE projects often bundlejson.lua.
Watch out for two mismatches between JSON and Lua: an empty table could be
an empty array [] or an empty object {}, and JSON null can't be
stored in a table (libraries provide a special sentinel value). Check
payloads with the JSON Formatter.