Decoupling simple config or any other drupal data

Using JSON API or commerce api or even JSON API resources is great but it is limited to entities and whole architecture is aimed at them. This is fine in most cases but what if you want to output some config or some random data. You will need to get creative a bit. So what we do is then make custom drupal 8 controller, you setup the usual router yml like

  path: '/jsonapi/my-resource'
    _controller: '\Drupal\decoupled_module\Controller\MyMethod::data'
    _title: 'Method data'
    _permission: 'access content'

and then in standard scaffolding of this controller you add what to output in this data method.


  public function data() {
    $regions = $this->configFactory->get('lelo_decoupled.settings')->get('empty_cart_products');
    $self_url = Url::fromUri('base:' . \Drupal::request()->getRequestUri())->setAbsolute()->toString(TRUE)->getGeneratedUrl();
    $data = [];

    $country = LfiGeoLocation::countryCode();
    $current_region = $this->regionRepository->getRegionByCountry($country);

    foreach ($regions as $label => $region) {
      if ($label == $current_region){
        $productVariations = $this->entityTypeManager->getStorage('commerce_product_variation')->loadMultiple($region);
        foreach ($productVariations as $key => $product) {
          $data[$label][$key] = ['data' => $product->toArray()];

    $response_data['jsonapi'] = [
      'version' => '1.0',
      'meta' => [
        'links' => [
          'self' => ['href' => ''],

    $response_data['data']['type'] = 'empty_cart--page';
    $response_data['data']['links'] = ['self' => ['href' => $self_url],];
    $response_data['data']['attributes'] = $data;

    return new JsonResponse($response_data);

What I did here is some custom code for mine particular purpose where I load info saved with config factory then I use that info to load drupal cmmerce products and info I need about them and then I expose that info and put it into data array, which in the end is added to output and formatted in json api format. So you can model your own solution similar to this one. In the end we should think about caching and add some cache tags and make some kind of CacheableJsonResponse, but this is something for future post.