SQLite JSON Support
Extracting Values
SQLite's JSON functions are available since version 3.9.0 (2015-10-14).
-- json_extract(json, path [, path...])
SELECT json_extract('{"name":"Alice","age":30}', '$.name');
-- Alice
SELECT json_extract('{"a":{"b":42}}', '$.a.b');
-- 42
-- Array access with [index]
SELECT json_extract('{"tags":["redis","sql"]}', '$.tags[0]');
-- redis
-- Multiple paths in one call
SELECT json_extract('{"a":1,"b":2}', '$.a', '$.b');
-- returns first found: 1
-- Shorthand -> and ->> operators (SQLite 3.38.0+)
SELECT data -> '$.name' FROM users; -- JSON value
SELECT data ->> '$.name' FROM users; -- text value
-- Use in WHERE clause
SELECT * FROM products
WHERE json_extract(metadata, '$.stock') > 0;
Building JSON
-- json_object(key, value, ...)
SELECT json_object('id', 1, 'name', 'Alice', 'active', 1);
-- {"id":1,"name":"Alice","active":1}
-- json_array(value, ...)
SELECT json_array(1, 'two', 3.14, NULL);
-- [1,"two",3.14,null]
-- json(): validate and minify
SELECT json(' { "a" : 1 } ');
-- {"a":1}
-- json_quote(): wrap value in JSON format
SELECT json_quote('hello'); -- "hello"
SELECT json_quote(42); -- 42
SELECT json_quote(NULL); -- null
-- Aggregate: json_group_array / json_group_object
SELECT json_group_array(name) FROM users;
-- ["Alice","Bob","Carol"]
SELECT json_group_object(id, name) FROM users;
-- {"1":"Alice","2":"Bob"}
json_each & json_tree
Table-valued functions that expand JSON into rows — useful for querying arrays.
-- json_each: iterate top-level array or object keys
SELECT key, value, type
FROM json_each('["apple","banana","cherry"]');
-- key=0, value=apple, type=text
-- key=1, value=banana, type=text
-- json_each with path
SELECT value FROM json_each('{"tags":["redis","sql"]}', '$.tags');
-- Use with a table column (JOIN syntax)
SELECT p.id, e.value AS tag
FROM products p, json_each(p.metadata, '$.tags') AS e;
-- json_tree: recursively expand (like json_each but deep)
SELECT key, value, type, path, fullkey
FROM json_tree('{"a":{"b":[1,2,3]}}');
-- Find products where any tag = 'sale'
SELECT DISTINCT p.*
FROM products p
JOIN json_each(p.metadata, '$.tags') t ON t.value = 'sale';
Modifying JSON
-- json_set: set values (creates if missing)
SELECT json_set('{"a":1}', '$.b', 2);
-- {"a":1,"b":2}
-- json_insert: insert only (no-op if path exists)
SELECT json_insert('{"a":1}', '$.a', 99);
-- {"a":1} (no change, key exists)
-- json_replace: replace only (no-op if path missing)
SELECT json_replace('{"a":1}', '$.b', 2);
-- {"a":1} (no change, key missing)
-- json_remove: delete a key or array element
SELECT json_remove('{"a":1,"b":2}', '$.a');
-- {"b":2}
SELECT json_remove('["x","y","z"]', '$[1]');
-- ["x","z"]
-- json_patch: RFC 7396 merge patch
SELECT json_patch('{"a":1,"b":2}', '{"b":null,"c":3}');
-- {"a":1,"c":3} (b removed because null, c added)
JSON Function Quick Reference
| Function | Description |
|---|---|
json(x) | Validate and minify JSON |
json_extract(j,p) | Extract value at path |
json_object(k,v,...) | Build a JSON object |
json_array(v,...) | Build a JSON array |
json_set(j,p,v) | Set (insert or replace) |
json_insert(j,p,v) | Insert only if missing |
json_replace(j,p,v) | Replace only if exists |
json_remove(j,p) | Delete key or element |
json_patch(j,p) | Merge patch (RFC 7396) |
json_each(j) | Expand JSON to rows |
json_tree(j) | Recursively expand JSON |
json_type(j,p) | Type of value at path |
json_valid(j) | 1 if valid JSON |