json_query
Extract and map fields from deeply nested JSON into Dart models without writing repetitive manual traversal code.
final response = {
'status': true,
'data': {
'user': {
'id': 123,
'profile': {'name': 'Ebrahim', 'avatar': '...'},
'subscription': {
'package': {'name': 'Fiber', 'speed': 100},
},
},
},
};
final user = JsonQuery(response).map<User>(
{
'id': '.data.user.id',
'name': '.data.user.profile.name',
'package': '.data.user.subscription.package.name',
},
User.fromJson,
);
No matter how deep or awkwardly-shaped the API response is, you say what
fields you want and what to do with them — json_query handles the
traversal.
Basic extraction
final id = JsonQuery(json).get('.data.user.id');
A missing field returns null instead of throwing:
JsonQuery(json).get('.data.user.nickname'); // null, no exception
Pass required: true when a missing value should be a hard error instead:
JsonQuery(json).get('.data.user.id', required: true); // throws JsonQueryAccessException if absent
Renaming fields into a flat map
JsonQuery(json).pick({
'id': '.data.user.user_id',
'name': '.data.user.full_name',
});
Lists
final names = JsonQuery(json).pickList(
'.data.users',
{'id': '.id', 'name': '.profile.name'},
);
Or apply a wildcard inline to project a field out of every element:
JsonQuery(json).get('.data.users[].id'); // [1, 2, 3]
Mapping straight to a Dart object
Works with a manual fromJson, json_serializable, or Freezed — anything
shaped like T Function(Map<String, dynamic>):
final user = JsonQuery(json).map<User>(
{'id': '.data.user.id', 'name': '.data.user.name'},
User.fromJson,
);
final users = JsonQuery(json).mapList<User>(
'.data.users',
{'id': '.id', 'name': '.name'},
User.fromJson,
);
Compiled queries
If you run the same projection against many payloads (e.g. once per item in a paginated list), compile it once to skip re-parsing the paths:
final query = JsonQuery.compile({
'id': '.data.user.id',
'name': '.data.user.profile.name',
});
final user = query.map<User>(json, User.fromJson);
Query syntax
.field,.a.b.c— dot field access[n]— array index[]— apply the rest of the path to every element of a list
That's the whole language. json_query is a JSON projection and mapping
tool for application developers, not a general-purpose JSON query language —
there is deliberately no filtering syntax, scripting, or arithmetic. See the
architecture notes for what's intentionally left out and why.
Error handling
JsonQuerySyntaxException— the path string itself is malformed.JsonQueryAccessException— only thrown whenrequired: trueand the path can't be resolved (wrong type along the way, missing field, out-of-range index).
By default, unresolvable paths simply evaluate to null.
Performance
- Operates directly on already-decoded
Map/List/dynamic— never touchesdart:convertitself. - A path string is parsed once into a
Listof segments, which is the compiled query — there's no separate AST or compiler stage. JsonQuery.compile()lets you parse a projection once and reuse it across many payloads.
See test/benchmark/bench_traversal.dart for a manual sanity comparison
against plain Map traversal.
HTTP client integration
json_query has zero HTTP dependency by design. Since Dio, package:http,
and Chopper responses are already decoded Map/List values, no
integration package is required to use json_query with any of them —
JsonQuery(response.data) works as-is.
Libraries
- json_query
- Extract and map fields from deeply nested JSON into Dart models without writing repetitive manual traversal code.