Skip to content

JSON Support

Weasel.Sqlite stores JSON data in TEXT columns and leverages the SQLite JSON1 extension for querying and indexing.

Verifying JSON1 Availability

Most SQLite builds include JSON1 by default. Verify with:

sql
SELECT json('{"test": true}');

If this returns {"test":true}, JSON1 is available.

JSON Columns

JSON data is stored as TEXT. Use a raw type string when adding a JSON column:

cs
var table = new Table("products");
table.AddColumn<int>("id").AsPrimaryKey().AutoIncrement();
table.AddColumn<string>("name").NotNull();
table.AddColumn("metadata", "TEXT"); // JSON column

snippet source | anchor

Querying JSON Data

Use json_extract() in SQL to access values within JSON columns:

sql
-- Extract a scalar value
SELECT id, json_extract(metadata, '$.category') as category
FROM products;

-- Filter on a JSON field
SELECT * FROM products
WHERE json_extract(metadata, '$.price') > 50.0;

-- Nested paths
SELECT json_extract(metadata, '$.dimensions.width') as width
FROM products;

Expression Indexes on JSON Paths

Create indexes on JSON paths using ForJsonPath() on IndexDefinition for efficient queries:

cs
var table = new Table("products");
table.AddColumn<int>("id").AsPrimaryKey().AutoIncrement();
table.AddColumn<string>("name").NotNull();
table.AddColumn("metadata", "TEXT");

// Index on a JSON field
var categoryIdx = new IndexDefinition("idx_products_category");
categoryIdx.ForJsonPath("metadata", "$.category");
table.Indexes.Add(categoryIdx);

// Unique index on a JSON field
var skuIdx = new IndexDefinition("idx_products_sku") { IsUnique = true };
skuIdx.ForJsonPath("metadata", "$.sku");
table.Indexes.Add(skuIdx);

snippet source | anchor

This generates an expression index using json_extract():

sql
CREATE INDEX "idx_products_category" ON "products" (json_extract(metadata, '$.category'));

JSON Views

Combine JSON extraction with views for a clean query interface:

cs
var view = new View("product_details", @"
SELECT id, name,
json_extract(metadata, '$.category') as category,
json_extract(metadata, '$.price') as price,
json_extract(metadata, '$.in_stock') as in_stock
FROM products");

snippet source | anchor

Full Example

cs
var table = new Table("events");
table.AddColumn<int>("id").AsPrimaryKey().AutoIncrement();
table.AddColumn<string>("type").NotNull();
table.AddColumn("payload", "TEXT"); // JSON data
table.AddColumn<string>("created_at").NotNull();

// Index for filtering events by JSON field
var idx = new IndexDefinition("idx_events_source");
idx.ForJsonPath("payload", "$.source");
table.Indexes.Add(idx);

// Generate and execute DDL
var migrator = new SqliteMigrator();
var writer = new StringWriter();
table.WriteCreateStatement(migrator, writer);

var connection = new SqliteConnection("Data Source=myapp.db");
await connection.OpenAsync();
var cmd = connection.CreateCommand();
cmd.CommandText = writer.ToString();
await cmd.ExecuteNonQueryAsync();

snippet source | anchor

Notes

  • JSON1 functions include json(), json_extract(), json_insert(), json_replace(), json_remove(), json_type(), json_array(), and json_object()
  • JSON data is stored as plain TEXT with no automatic validation unless you use json() or CHECK constraints
  • Expression indexes on JSON paths allow SQLite to use indexed lookups for json_extract() queries
  • STRICT mode tables require TEXT type for JSON columns (which is the default mapping)

Released under the MIT License.