Skip to content
AgileLogics
5 min read

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 bundle json.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.