Skip to content

JSON

MiniSQL has a native JSON column type that validates and stores JSON data. JSON columns support path navigation with -> / ->> operators, containment queries with JSON_CONTAINS, and optional inverted index acceleration.


The JSON type

CREATE TABLE events (
    id      INT8 PRIMARY KEY AUTOINCREMENT,
    created TIMESTAMP DEFAULT NOW(),
    payload JSON NOT NULL
);
  • Values must be valid JSON; invalid JSON is rejected on insert and update.
  • Stored as compact UTF-8 text (whitespace is not preserved).
  • Size is unlimited (large values use overflow pages).
  • Validated automatically — no application-level validation needed.

Inserting JSON

-- JSON object
INSERT INTO events (payload) VALUES ('{"action": "login", "user": "alice", "uid": 42}');

-- JSON array
INSERT INTO events (payload) VALUES ('["go", "sql", "database"]');

-- Nested
INSERT INTO events (payload) VALUES ('{"meta": {"version": 2}, "tags": ["a", "b"]}');

In Go:

_, err = db.Exec(
    `INSERT INTO events (payload) VALUES (?)`,
    `{"action": "purchase", "amount": 99.99}`,
)

Path operators

-> — JSON fragment

Returns the value at a key or array index as a JSON string.

SELECT payload -> 'action'  FROM events;   -- '"login"'
SELECT payload -> 'user'    FROM events;   -- '"alice"'
SELECT payload -> 0         FROM events;   -- first element as JSON

->> — SQL scalar

Returns the value as a SQL string or number.

SELECT payload ->> 'action' FROM events;   -- 'login'
SELECT payload ->> 'uid'    FROM events;   -- '42'
SELECT payload ->> 0        FROM events;   -- first element as string

Chaining

SELECT payload -> 'meta' -> 'version' FROM events;   -- '2' (JSON)
SELECT payload -> 'meta' ->> 'version' FROM events;  -- '2' (scalar)

Filtering on JSON fields

-- Equality on extracted scalar
SELECT * FROM events WHERE payload ->> 'action' = 'login';

-- Numeric comparison (cast to INT8 first)
SELECT * FROM events WHERE CAST(payload ->> 'uid' AS INT8) > 100;

-- Nested field
SELECT * FROM events WHERE payload -> 'meta' ->> 'version' = '2';

-- Array element
SELECT * FROM events WHERE payload ->> 0 = 'go';

JSON functions

Function Description
JSON_CONTAINS(json, val) True if json contains val as a sub-document or element
JSON_EXTRACT(json, path) Extract scalar at path
JSON_TYPE(json [, path]) Type of the JSON value: 'object', 'array', 'string', 'number', 'boolean', 'null'
JSON_ARRAY_LENGTH(json [, path]) Number of elements in a JSON array
JSON_VALID(json) 1 if valid JSON, 0 otherwise

See JSON Functions for full examples.


JSON inverted index

For fast containment queries, create an inverted index on a JSON column:

CREATE INVERTED INDEX idx_events_payload ON events (payload);

-- Index-accelerated containment query
SELECT * FROM events WHERE JSON_CONTAINS(payload, '{"action": "login"}');

See JSON Inverted Index for details.


Examples

-- Create table with JSON column
CREATE TABLE sessions (
    id      UUID      PRIMARY KEY,
    user_id INT8      NOT NULL,
    meta    JSON
);

INSERT INTO sessions (id, user_id, meta) VALUES
    ('550e8400-e29b-41d4-a716-446655440001', 1, '{"ip": "1.2.3.4", "ua": "Firefox"}'),
    ('550e8400-e29b-41d4-a716-446655440002', 2, '{"ip": "5.6.7.8", "ua": "Chrome"}');

-- Find sessions from a specific IP
SELECT user_id FROM sessions WHERE meta ->> 'ip' = '1.2.3.4';

-- Aggregate by user-agent family
SELECT meta ->> 'ua' AS browser, COUNT(*) AS cnt
FROM sessions
GROUP BY meta ->> 'ua'
ORDER BY cnt DESC;