Skip to content

Commit 9426bff

Browse files
authored
Added filtering support for collections (#97)
1 parent bd3e138 commit 9426bff

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

lib/query.dart

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
library query;
22

33
export 'package:json_api/src/query/fields.dart';
4+
export 'package:json_api/src/query/filter.dart';
45
export 'package:json_api/src/query/include.dart';
56
export 'package:json_api/src/query/page.dart';
67
export 'package:json_api/src/query/query_parameters.dart';

lib/src/query/filter.dart

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:json_api/src/query/query_parameters.dart';
2+
3+
/// Query parameters defining Filter
4+
/// @see https://jsonapi.org/recommendations/#filtering
5+
class Filter extends QueryParameters {
6+
/// The [filter] argument maps the resource type to a list of filters.
7+
///
8+
/// Example:
9+
/// ```dart
10+
/// Filter({'articles': ['title', 'body'], 'people': ['name']}).addTo(url);
11+
/// ```
12+
/// encodes to
13+
/// ```
14+
/// ?filter[articles]=title,body&filter[people]=name
15+
/// ```
16+
Filter(Map<String, List<String>> filter)
17+
: _filter = {...filter},
18+
super(filter.map((k, v) => MapEntry('filter[$k]', v.join(','))));
19+
20+
/// Extracts the requested filter from the [uri].
21+
static Filter fromUri(Uri uri) => Filter(uri.queryParameters
22+
.map((k, v) => MapEntry(_regex.firstMatch(k)?.group(1), v.split(',')))
23+
..removeWhere((k, v) => k == null));
24+
25+
List<String> operator [](String key) => _filter[key];
26+
27+
static final _regex = RegExp(r'^filter\[(.+)\]$');
28+
29+
final Map<String, List<String>> _filter;
30+
}

test/unit/query/filter_test.dart

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:json_api/src/query/filter.dart';
2+
import 'package:test/test.dart';
3+
4+
void main() {
5+
test('Can decode url', () {
6+
final uri = Uri.parse(
7+
'/articles?include=author&filter%5Barticles%5D=title%2Cbody&filter%5Bpeople%5D=name');
8+
final filter = Filter.fromUri(uri);
9+
expect(filter['articles'], ['title', 'body']);
10+
expect(filter['people'], ['name']);
11+
});
12+
13+
test('Can add to uri', () {
14+
final filter = Filter({
15+
'articles': ['title', 'body'],
16+
'people': ['name']
17+
});
18+
final uri = Uri.parse('/articles');
19+
20+
expect(filter.addToUri(uri).toString(),
21+
'/articles?filter%5Barticles%5D=title%2Cbody&filter%5Bpeople%5D=name');
22+
});
23+
}

0 commit comments

Comments
 (0)