JSON Columns
Store and query JSON data directly in your SQL tables. JSON columns are useful for flexible, semi-structured data that doesn't fit a rigid schema.
Feature Support Matrix
Feature | PostgreSQL | MySQL/MariaDB | SQLite |
---|---|---|---|
Basic JSON equality (whereJson ) | ✓ | ✓ | ✓ |
Nested property match | ✓ | ✓ | ~ |
Array element match | ✓ | ✓ | ~ |
AND/OR JSON conditions | ✓ | ✓ | ~ |
JSON containment (whereJsonContains ) | ✓ | ✓ | ✗ |
JSON IN/NOT IN | ✓ | ✓ | ✓ |
Select JSON column | ✓ | ✓ | ✓ |
~ = Limited/partial support, see SQLite JSON Limitations
Basic JSON Filtering
Query for full JSON object equality or by nested properties.
// Full object equality
await User.query().whereJson("json", { foo: "bar", arr: [1, 2, 3] }).first();
// Nested property (works best in PostgreSQL/MySQL)
await User.query().whereJson("json", { profile: { info: { age: 42 } } } ).first();
Logical Operations (AND/OR)
Combine multiple JSON conditions using andWhereJson
and orWhereJson
.
// AND combination
await User.query()
.whereJson("json", { logic: "A" })
.andWhereJson("json", { status: "active" })
.first();
// OR combination
await User.query()
.whereJson("json", { logic: "A" })
.orWhereJson("json", { logic: "B" })
.many();
Note: Complex AND/OR combinations are only fully supported in PostgreSQL/MySQL. SQLite has limited support. See SQLite JSON Limitations.
Array and Object Filtering
Query by array elements or nested object properties in JSON columns.
// Array element match (best in PostgreSQL/MySQL)
await User.query().whereJson("json", { tags: ["frontend", "typescript"] }).first();
// Nested object property
await User.query().whereJson("json", { user: { profile: { settings: { theme: "dark" } } } }).first();
Data Variations
Insert and retrieve various JSON structures, including primitives and null.
const variants = [
{ foo: "bar", arr: [1, 2, 3], nested: { a: 1 } },
{ simple: "string value" },
{ number: 12345 },
{ bool: true },
null,
];
for (const json of variants) {
await User.insert({ ...UserFactory.getCommonUserData(), json });
}
Bulk Operations
Insert many users with different JSON values and query using whereJson
or whereJsonIn
.
await User.insertMany([
{ ...UserFactory.getCommonUserData(), json: { bulk: 1 } },
{ ...UserFactory.getCommonUserData(), json: { bulk: 2 } },
]);
await User.query().whereJson("json", { bulk: 1 }).first();
await User.query().whereJsonIn("json", [{ bulk: 1 }, { bulk: 2 }]).many();
Advanced JSON Filters
Use containment and negation for advanced filtering (PostgreSQL/MySQL only).
// Containment (not supported in SQLite)
await User.query().whereJsonContains("json", { arr: [1, 2, 3] }).first();
await User.query().whereJsonNotContains("json", { arr: [1, 2, 3] }).first();
// Negation
await User.query().whereNotJson("json", { foo: "bar" }).first();
Selecting JSON Columns
Select only the JSON column or combine with other columns.
// Select only JSON
await User.query().select("json").where("email", "=", user.email).first();
// Select JSON and another column
await User.query().select("json", "email").where("email", "=", user.email).first();
Cross-Database Notes
- PostgreSQL/MySQL/MariaDB: Full support for advanced JSON queries, containment, and deep property matching.
- SQLite: Only supports basic equality and simple queries. Advanced features (containment, deep property, array matching) are limited or unsupported. See SQLite JSON Limitations for details.
See also: