Beyond just storing JSON in a column (covered elsewhere on this site), Eloquent provides specific query methods for actually searching and filtering based on values inside that JSON structure, at the database level rather than pulling every row into PHP to check manually.
The example data structure
// a 'metadata' JSON column on a products table
{"color": "blue", "tags": ["sale", "featured"], "dimensions": {"width": 10, "height": 20}}
Querying a top-level JSON key
$blueProducts = Product::where('metadata->color', 'blue')->get();
Querying a nested JSON key
$products = Product::where('metadata->dimensions->width', 10)->get();
The -> syntax chains as deep as the actual JSON structure goes — each arrow descends one more level into the nested object.
Checking if a JSON array contains a specific value
$saleProducts = Product::whereJsonContains('metadata->tags', 'sale')->get();
Checking if a JSON array contains multiple specific values
$products = Product::whereJsonContains('metadata->tags', ['sale', 'featured'])->get();
Checking the length of a JSON array
$multiTaggedProducts = Product::whereJsonLength('metadata->tags', '>', 1)->get();
Combining JSON conditions with regular where clauses
$products = Product::where('active', true)
->where('metadata->color', 'blue')
->whereJsonContains('metadata->tags', 'sale')
->get();
JSON query methods chain naturally alongside regular column conditions — there's no special syntax needed to combine them in the same query.
Database support varies for JSON querying
MySQL 5.7+, PostgreSQL, and SQLite (recent versions) all support these JSON query methods, but the underlying SQL each generates is genuinely different per database, and JSON querying performance varies meaningfully by database engine — for a table doing frequent, performance-sensitive JSON filtering, checking your specific database's JSON indexing capabilities (like MySQL's generated columns with an index on a specific JSON path) is worth investigating.
When JSON querying signals it's time for real columns instead
If a specific JSON key is being filtered or sorted on frequently enough that query performance genuinely matters, that's often a sign the value deserves to be promoted to its own real, indexed database column instead — JSON storage suits data that's flexible and infrequently queried, not a permanent substitute for proper relational structure once a specific field becomes a core, frequently-filtered part of the application's actual query patterns.