One of SQLite’s strengths is its flexibility-it can handle relational data as well as semi-structured data like JSON. JSON (JavaScript Object Notation) has emerged as a popular data interchange format due to its simplicity, readability, and portability. Many applications today need to store and query JSON data.
It becomes easy to work with SQLite JSON data easy through its built-in JSON support. You can store JSON values in SQLite and use JSON functions to query, modify, and extract data from JSON documents stored in the database.
In this comprehensive guide, you will learn how to:
- Store JSON documents in SQLite
- Query and extract data from JSON columns using JSON functions
- Modify JSON values in SQLite using various JSON functions
- Index and optimize queries on JSON columns
- Migrate JSON data between SQLite and other databases
We will explore all of these topics in detail with easy-to-follow examples. Let’s dive in!
How to Store JSON in SQLite
To store JSON in an SQLite database, you can use a TEXT
or BLOB
column type. JSON data is basically text, so the TEXT
column is most commonly used.
Here is an example showing how to create a SQLite table with a JSON
column and insert JSON data into it:
-- Create table
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name TEXT,
address JSON
);
-- Insert JSON data
INSERT INTO employees VALUES
(1, 'John Doe', '{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
}');
-- Verify inserted data
SELECT * FROM employees;
This stores the employee’s address as a JSON object in the address
column. The JSON data is treated as text and stored as-is in the column.
Some key points about storing JSON in SQLite:
- JSON data must be valid JSON syntax. Invalid JSON values will result in an error.
- JSON values can be inserted programmatically by generating JSON strings from code.
- JSON text can include whitespace and indentation to make it human-readable. SQLite will store it as-is.
- If needed, JSON can be minified before storing to reduce storage space.
- BLOB can also be used instead of TEXT but offers no advantages for JSON storage.
This provides the basic capability to store JSON documents in your SQLite database. Next, let’s see how to query and manipulate this JSON data.
How to Query JSON Data in SQLite
SQLite provides a set of JSON functions that allow you to query values stored in JSON columns. These functions give you the ability to extract specific values from JSON documents using a JSON path.
The key functions for querying JSON data are:
json_extract
– Extract a scalar value from JSON using pathjson_type
– Get type of value extracted from JSONjson_valid
– Validate if a string contains valid JSON
Let’s see examples of using these functions:
-- Get city for employee id 1
SELECT json_extract(address, '$.city')
FROM employees
WHERE id = 1;
-- Get type of postalCode value
SELECT json_type(address, '$.postalCode')
FROM employees
WHERE id = 1;
-- Validate JSON
SELECT json_valid('{ "name": "John" }');
The json_extract
function lets you pull out specific values from a JSON document by specifying the path. Note the $
prefix before the path.
Some things to know about JSON paths:
- Path starts with
$
to indicate root element - Use
.
to specify nested fields like$.address.city
- Use
[n]
for array access like$.phoneNumbers[0]
*
can be used as wildcard for anything
The json_type
function returns the JSON type of the extracted value – integer
, real
, text
, blob
, etc.
And json_valid
lets you verify if a string contains valid JSON or not.
In addition to these, there are several other JSON functions like json_array
, json_object
, json_insert
, json_replace
that can create or modify JSON values. We will see examples of using these later.
How to Access JSON Fields in SQLite Query
You can directly access JSON fields in other parts of the query like the WHERE clause, JOIN
condition, ORDER BY, etc.
SQLite allows you to specify a path with the ->>
operator to extract a JSON value. For example:
-- Get employees in New York
SELECT *
FROM employees
WHERE address->>'$.city' = 'New York';
-- Order by zip code
SELECT *
FROM employees
ORDER BY address->>'$.postalCode';
This shorthand is equivalent to using json_extract
but provides cleaner syntax in queries.
How to Modify JSON values in SQLite
In addition to querying JSON columns, SQLite also provides functions to modify, insert, update, or delete data from JSON documents.
Some common JSON modification functions are:
json_set
– Set value of a JSON elementjson_insert
– Insert into a JSON array or objectjson_replace
– Replace value of a JSON elementjson_remove
– Remove element from JSON
Let’s see how to use these functions to manipulate JSON values:
-- Change city to Chicago
UPDATE employees
SET address = json_set(address, '$.city', 'Chicago')
WHERE id = 1;
-- Add a phone number
UPDATE employees
SET address = json_insert(address, '$.phoneNumbers[0]', '123-456-7890')
WHERE id = 1;
-- Change postal code
UPDATE employees
SET address = json_replace(address, '$.postalCode', '60611')
WHERE id = 1;
-- Remove state
UPDATE employees
SET address = json_remove(address, '$.state')
WHERE id = 1;
You can see how these functions allow modifying JSON documents by inserting, replacing, or removing elements as needed.
Some key points:
json_set
will add new element if path doesn’t existjson_insert
only inserts if path existsjson_replace
replaces value if path exists else no change- Removed elements using
json_remove
cannot be restored
These functions enable updating your JSON documents just like you would update rows or columns in a relational table.
How to Index JSON Columns in SQLite
To optimize performance, you may want to create indexes on your JSON columns – especially if they are used frequently for filtering or sorting.
SQLite allows you to index expressions, so you can create indexes on specific JSON fields like:
-- Index for postal code
CREATE INDEX idx_postal_code ON employees((address->>'$.postalCode'));
-- Multi-column index
CREATE INDEX idx_address ON employees(address->>'$.city', address->>'$.state');
This can speed up queries like:
-- Make use of index
SELECT *
FROM employees
WHERE address->>'$.postalCode' = '60611';
You should create indexes to match your typical query patterns and filters. Here are some tips:
- Prefer indexes on smaller TEXT/INTEGER over larger BLOB/strings
- Use multi-column indexes for queries filtering on multiple fields
- Limit indexes to only required columns – avoid indexing entire JSON
- Test queries with/without indexes to validate performance gains
Also, rebuilding indexes after large data modifications in JSON can restore optimal performance.
How to Handle Nested JSON Data in SQLite
In real-world scenarios, JSON documents can have complex nested structures with multiple levels of arrays and objects. SQLite’s JSON functions work consistently across nested data.
Consider a JSON document like:
{
"name": "John",
"age": 35,
"address": {
"line1": "123 Main St",
"city": "Chicago",
"state": "IL",
"zip": 60611
},
"phoneNumbers": [
"123-456-7890",
"098-765-4321"
]
}
To access nested fields and arrays, you simply extend the JSON path:
-- Access nested fields
SELECT json_extract(data, '$.address.city') FROM users WHERE ...
-- Get array element
SELECT json_extract(data, '$.phoneNumbers[0]') FROM users WHERE ...
-- Nested array access
SELECT json_extract(data, '$.address.line2[0]') FROM users WHERE ...
JSON functions seamlessly handle arbitrarily complex nested data structures.
One exception is the json_array()
function which accepts scalar values as arguments. To insert nested JSON arrays/objects into another JSON document, you need to:
- Construct nested JSON separately
- Insert it using
json_insert()
orjson_set()
For example:
-- Construct nested JSON
SELECT json_array(json_object('line1', '123 Main St'));
-- Insert into document
UPDATE users
SET data = json_insert(data, '$.address.line2',
json_array(json_object('line1', '123 Main St')))
WHERE ...
So you need to build up nested structures before inserting into the main document.
How to Migrate JSON Data from SQLite
A common requirement is migrating JSON data from SQLite to another database or file format like MongoDB, DynamoDB, CSV, etc.
This is straightforward – you extract the JSON data and export it to the desired target system. Here is an example showing how to extract JSON data from SQLite and convert to CSV:
-- Query JSON data
SELECT json_extract(data, '$.name') AS name,
json_extract(data, '$.age') AS age,
json_extract(data, '$.address.line1') AS line1,
json_extract(data, '$.address.city') AS city
FROM users;
-- Export output to CSV
.mode csv
.headers on
.output data.csv
This exports extracted fields to a CSV file that can be loaded elsewhere.
You can use similar techniques to export JSON documents to any external datastore:
- Extract required fields or full JSON
- Optionally transform to another format
- Load into target datastore
SQLite’s JSON functions provide the flexibility to easily migrate your JSON data.
Summary of Best Practices of JSON in SQLite
To summarize, here are some recommended best practices for working with JSON in SQLite:
- Use TEXT columns to store JSON by default rather than BLOB
- Validate syntax before insertion to prevent errors
- Normalize over nesting where possible for simpler querying
- Use JSON functions like
json_extract
for querying instead of string functions - Index common fields used for filters and sorting
- Construct nested JSON before insertion into documents
- Extract data rather than entire columns when migrating
- Test integrations with sample data before production migrations
By following these best practices, you can build robust applications on SQLite that leverage its JSON capabilities.
Conclusion
This guide covered the key aspects of working with JSON data in SQLite:
- Storing JSON documents in TEXT columns
- Querying and extracting values using json_extract and other JSON functions
- Modifying JSON values with json_set, json_insert, json_replace etc
- Creating indexes on JSON fields for performance
- Dealing with nested JSON structures
- Migrating JSON data from SQLite
As you can see, SQLite provides extensive support through its built-in JSON handling functions. You can store, query, and manipulate JSON just like you would with regular relational data.