Skip to content

Json

Converts Lua values to JSON text and back: to talk to a web service, or to keep data in a file that other programs can read too.

Json:encode makes text of a value, Json:decode makes a value of a text:

Lua JSON
a table with the keys 1, 2, 3, ... an array
a table with strings as keys an object
an empty table an empty array, or with Json:object an empty object
a string a string
a number a number
a boolean true or false
Json.null null

An integer stays an integer, a float stays a float, and neither loses digits: 2.0 is written as 2.0, and 9007199254740993 stays exactly that. A web service that wants a whole number and gets the result of 10 / 2, which is the float 5.0, may refuse it: 10 // 2 gives the integer 5.

A JSON text is UTF-8, and so are a spell's strings, so umlauts and emoji pass unchanged.

Both functions return at once, without a tick passing, so they can be used in an event interceptor. The server waits for them meanwhile: a text of 1 MB takes about 30 ms, and a tick has 50 ms.

Example: Keep settings in a file

local function loadSettings(path)
  local file = io.open(path, "r")
  if not file then
    return {}
  end
  local text = file:read("a")
  file:close()
  return assert(Json:decode(text))
end

local function saveSettings(path, settings)
  local file = assert(io.open(path, "w"))
  file:write(Json:encode(settings, { pretty = true }))
  file:close()
end

local settings = loadSettings("settings.json")
settings.visits = (settings.visits or 0) + 1
saveSettings("settings.json", settings)

Fields

null: userdata — Read-Only

The value that stands for a JSON null. Put it where a null shall be written, and compare with it to find one that was read: value == Json.null. It counts as true in a condition.

Methods

decode(text: string) → value: any, reason: string?

Reads a JSON text and returns its value. Call it on the class: Json:decode(text).

A text that is no valid JSON is no error: the function returns nil and the reason, as such a text usually comes from elsewhere. Only the end of the text may follow the value.

An object becomes a table with strings as keys. A key with the value null is left out of it, as a Lua table can't hold a nil. An array becomes a table with the keys 1, 2, 3, ... and a null in it becomes Json.null, so the other values keep their places.

A table made from an object stays an object when encode writes it, even if it is empty. So a file read and written again keeps its {} and [].

The nesting is limited to 200 levels.

Example: Read a value

local data, reason = Json:decode('{"name":"Abby","scores":[3,1,2]}')
if data then
  print(data.name, data.scores[1])
else
  print("Not JSON: " .. reason)
end

Parameters

  • text: string — The JSON text.

Returns

  • value: any — The value, or nil if the text is no valid JSON. A text that is just a null gives Json.null.
  • reason: string? — Why the text can't be read.

encode(value: any, options?: {pretty?:boolean}) → text: string

Writes a value as a JSON text. Call it on the class: Json:encode(value).

Raises an error for what JSON can't hold:

  • a function, a coroutine, a spell, an entity, a block, an item, or any other object of the game (Vec3 is fine: it is a table with x, y and z)

  • nil, also as a hole in an array: use Json.null there

  • a table with both numbers and strings as keys, or with other keys

  • a table that contains itself, or a nesting of more than 200 levels

  • a number that isn't one: nan, inf, -inf

  • a string that isn't valid UTF-8

The keys of an object are sorted, so the same table always gives the same text. A table's metatable doesn't count, just the table's own fields.

Example: Write a value

local text = Json:encode({ name = "Abby", scores = { 3, 1, 2 } })
print(text) -- {"name":"Abby","scores":[3,1,2]}

Example: Write it for people to read

print(Json:encode({ name = "Abby" }, { pretty = true }))

Parameters

  • value: any — The value to write.
  • options?: {pretty?:boolean} — With pretty, the text gets line breaks and indentation. Defaults to false.

Returns

  • text: string — The JSON text.

object() → object: table

Returns a new empty table that encode writes as an object, as an empty table is written as an array. Call it on the class: Json:object(). Otherwise it is a table like any other, and it stays an object when it gets keys and loses them again.

Example: Tell an empty object from an empty array

print(Json:encode({ list = {}, options = Json:object() })) -- {"list":[],"options":{}}

Returns

  • object: table — The new table.