Skip to main content
Version: 1.2.1

Automatic JSON Columns

OrvexORM can automatically convert Lua tables to JSON for database storage, and convert them back when you read them. This is perfect for saving positions, inventories, configurations, etc.

The "json" type (explicit)

When you declare a field as "json", OrvexORM knows it needs to convert tables to JSON:

local Player = ORM.model("players", {
identifier = "string",
position = "json", -- Lua table ↔ JSON automatically
inventory = "json",
})

Saving

Player.create({
identifier = "license:abc",
position = { x = 100.5, y = 200.3, z = 50.0 },
inventory = {
{ item = "bread", count = 5 },
{ item = "water", count = 3 },
},
})

In the database, position is stored as:

{"x":100.5,"y":200.3,"z":50.0}

Reading

local player = Player.find({ identifier = "license:abc" })

-- It's automatically converted back to a Lua table
print(player.position.x) -- 100.5
print(player.inventory[1].item) -- "bread"

You don't have to do anything — the conversion is transparent.

The "auto" type (automatic detection)

The "auto" type automatically detects whether a value needs to be converted:

  • On write: if the value is a table -> encode as JSON
  • On read: if the value looks like JSON (starts with { or [) -> decode to a table
local Config = ORM.model("configs", {
key = "string",
value = "auto", -- detects automatically
})

-- Save a table → stored as JSON
Config.create({ key = "spawn_point", value = { x = 100, y = 200, z = 50 } })

-- Save a string → stays a string
Config.create({ key = "server_name", value = "My RP Server" })

-- Save a number → stays a number
Config.create({ key = "max_players", value = 64 })

-- On read, everything is converted back correctly
local spawn = Config.find({ key = "spawn_point" })
print(spawn.value.x) -- 100 (Lua table)

local name = Config.find({ key = "server_name" })
print(name.value) -- "My RP Server" (string)

Difference between "json" and "auto"

"json""auto"
Writing a tableEncodes to JSONEncodes to JSON
Writing a stringNo conversionNo conversion
Reading a JSON stringDecodes to tableDecodes to table
Reading a regular stringDecodes to table (may break)Stays a string
ValidationChecks that it's a tableNo strict validation

:::tip Which one to choose?

  • "json": when the column always contains JSON (position, inventory, vehicle mods)
  • "auto": when the column can contain different types of values (configurations, metadata) :::

JSON column examples

Player position

local Player = ORM.model("players", {
identifier = "string",
position = "json",
})

-- Save
Player.upsert({
identifier = "license:abc",
position = { x = 123.4, y = 567.8, z = 90.1, heading = 180.0 },
})

Vehicle modifications

local Vehicle = ORM.model("vehicles", {
id = "number",
plate = "string",
mods = "json",
})

Vehicle.create({
plate = "ABC123",
mods = {
engine = 3,
brakes = 2,
color = { r = 255, g = 0, b = 0 },
neon = true,
},
})

Inventory

local Inventory = ORM.model("inventories", {
id = "number",
owner = "string",
items = "json",
})

Inventory.create({
owner = "license:abc",
items = {
{ name = "bread", count = 5, metadata = {} },
{ name = "water", count = 3, metadata = {} },
{ name = "phone", count = 1, metadata = { number = "555-0123" } },
},
})

local inv = Inventory.find({ owner = "license:abc" })
for _, item in ipairs(inv.items) do
print(item.name .. " x" .. item.count)
end

For JSON columns, use the JSON or LONGTEXT type in MySQL:

CREATE TABLE `players` (
`identifier` VARCHAR(60) NOT NULL,
`position` JSON DEFAULT NULL,
`inventory` JSON DEFAULT NULL,
PRIMARY KEY (`identifier`)
);