Beta documentation. This is an early preview — content is still in active development. Feedback helps shape the final release. Share your thoughts or join the discussion.

Decoder

The `decoder` library converts transport formats back to Lua data — JSON from APIs, base64 from uploads, hex from signatures.

On this page

Parse incoming data

The decoder library converts transport formats back to Lua data — JSON from APIs, base64 from uploads, hex from signatures.

Each function mirrors its encoder counterpart. Input → output.

Function reference

Function Example Result
decoder.json(s) decoder.json('{"a":1}') { a = 1 }
decoder.base64(s) decoder.base64("aGVsbG8=") "hello"
decoder.base36(s) decoder.base36("wanek4") "test"
decoder.hex(s) decoder.hex("68656c6c6f") "hello"
decoder.rot13(s) decoder.rot13("uryyb") "hello"

decoder.json — The most used function

-- Parse an API response
local res = http.get("https://api.example.com/data")
if res.status == 200 then
    local data = decoder.json(res.body)
    print(data.name)        -- access parsed fields
    print(data.items[1])    -- arrays work too
end

decoder.base64 — Decode transport data

-- Decode a base64 payload from a webhook
local raw = decoder.base64(webhook_payload)
-- Use the decoded string

decoder.hex — Hex to binary

-- Useful when working with crypto signatures
local bytes = decoder.hex("68656c6c6f")
-- → "hello"

Practical: parsing a webhook

app:post("/webhook/stripe", function(ctx)
    -- Verify the signature
    local signature = req.headers["stripe-signature"]
    local expected = hash.hmac(STRIPE_SECRET, req.body)

    if not hash.equals(signature, expected) then
        log.warn("Invalid webhook signature from " .. env.remote_ip)
        return ctx:error("Invalid signature", 401)
    end

    -- Parse the event
    local event = decoder.json(req.body)

    if event.type == "checkout.session.completed" then
        local session = event.data.object
        local order_id = session.metadata.order_id

        -- Fulfill the order
        api.dataset.update(tonumber(order_id), {
            data = { status = "paid", paid_at = os.date() }
        })
        log.info("Order " .. order_id .. " paid")
    end

    return ctx:ok(true)
end, { csrf = false })

Practical: import from external API

app:get("/import/products", function(ctx)
    local res = http.get("https://api.partner.com/products", {
        headers = { ["authorization"] = "Bearer " .. PARTNER_KEY }
    })

    if res.status ~= 200 then
        return ctx:error("Import failed", 502)
    end

    local products = decoder.json(res.body)
    local count = 0

    for _, product in ipairs(products) do
        api.dataset.create("products", {
            name = product.title,
            price = product.price,
            source = "partner_api"
        })
        count = count + 1
    end

    return { imported = count }
end)

Next: Hash & Crypto — verify data, generate tokens, create UUIDs.

Previous Encoder Next Hash & Crypto