JSON
Ormed has first-class JSON support across models and query builder APIs.
Prerequisites
What You’ll Learn
- How to query JSON fields with helper and selector syntax
- How JSON indexing and path semantics behave
- How to update JSON payloads through query and model workflows
Step Outcome
By the end of this page, you should be able to map JSON columns, filter by JSON paths, and apply partial JSON updates without replacing full documents.
Ormed supports:
- JSON fields on models via casts/codecs
- JSON path filters via
whereJson*helpers - JSON selector syntax with
->/->> - JSON path/patch updates from query and tracked-model APIs
note
These examples focus on JSON operations only. They assume you already have a working DataSource.
1. Define JSON Model Fields
(table: 'users')
class User extends Model<User> {
const User({required this.id, required this.email, this.metadata});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String email;
// Use the built-in `json` cast key for JSON objects.
(cast: 'json')
final Map<String, Object?>? metadata;
}
2. Query JSON Data
In Dart strings, $ is interpolation — if you write selectors with $.path, use raw strings (r'...'), or omit the $ prefix (metadata->>mode).
Array indexes can be addressed as either:
items[0](explicit), oritems.0(shorthand; normalized toitems[0])
If you need a numeric object key, use bracket quoting: items["0"].
- Helpers
- Selector syntax
- Indexing
Future<List<User>> jsonWhereHelpers(DataSource dataSource) {
return dataSource
.query<$User>()
.whereJsonContains('metadata', 'Dart', path: r'$.skills')
.whereJsonContainsKey('metadata', r'$.flags')
.whereJsonLength('metadata->tags', '>=', 2)
.whereJsonOverlaps('metadata->skills', ['Dart', 'Go'])
.get();
}
Future<List<User>> jsonWhereSelectorSyntax(DataSource dataSource) {
return dataSource
.query<$User>()
// `->` extracts JSON, `->>` extracts text for comparisons/sorting.
// If you include `$.path` in a Dart string, prefer raw strings `r'...'`.
.where(r'metadata->>$.mode', 'dark')
// You can also omit the `$` prefix (`mode` normalizes to `$.mode`).
.where('metadata->>mode', 'dark')
.where(r'metadata->$.featured', true)
.orderBy('metadata->>createdBy')
.get();
}
Future<List<User>> jsonWhereIndexing(DataSource dataSource) {
return dataSource
.query<$User>()
// Array index addressing: `items[1]` and `items.1` are equivalent.
.where(r'metadata->>$.meta.profile.items[1].label', 'b')
.where(r'metadata->>$.meta.profile.items.1.label', 'b')
// Numeric object keys are different: use bracket quoting.
.whereJsonContainsKey('metadata', r'$.items["0"]')
.get();
}
3. Update JSON Values
- Query update
- Tracked model
Future<void> jsonUpdateQuery(DataSource dataSource) async {
await dataSource.query<$User>().whereEquals('id', 1).update(
{'email': 'updated@example.com'},
jsonUpdates: (_) => [
JsonUpdateDefinition.path('metadata', r'$.meta.count', 5),
JsonUpdateDefinition.selector('metadata->mode', 'light'),
// Update JSON array elements (both forms normalize the same way).
JsonUpdateDefinition.path(
'metadata',
r'$.meta.profile.items[1].label',
'b2',
),
JsonUpdateDefinition.path(
'metadata',
r'$.meta.profile.items.0.label',
'a2',
),
JsonUpdateDefinition.patch('metadata', {
'flags': {'beta': true},
}),
],
);
}
Future<void> jsonUpdateModel($User user) async {
// Queue JSON updates on the tracked model, then save.
user.jsonSetPath('metadata', r'$.meta.count', 5);
user.jsonSet('metadata->mode', 'light');
user.jsonSetPath('metadata', r'$.meta.profile.items.0.label', 'a2');
user.jsonPatch('metadata', {
'flags': {'beta': true},
});
await user.save();
}
Practical Rules
- Use helper methods (
whereJsonContains,whereJsonLength,whereJsonContainsKey) for portability and readability. - Use raw selector syntax for advanced expressions or mixed SQL/JSON predicates.
- Prefer path/patch updates over full document replacement to reduce write size.
Verify Your Setup
- JSON model fields round-trip through your driver.
- JSON selector filters return expected rows for both object keys and array indexes.
- Partial JSON updates preserve unrelated keys.