How to use a custom router?

Custom routers do indeed support JSON responses:

$router = new Router();
$router->register(array(
    array(
        'pattern' => 'test',
        'method'  => 'GET',
        'action'  => function() {
            return response::json(['this' => ['is', 'a', 'test']]);
        }
    )
));

if($route = $router->run()) {
  $response = call($route->action(), $route->arguments());
  die($response);
}

Tested with Kirby 2.5.5-RC1.

You can also use filters with the c::set('routes') approach, just not “global” filters. But adding a filter callback to the route array should definitely work.