Add computed field to JSON:API response

Add computed field to JSON:API response

Drupal 8 now provides an out-of-the-box JSON:API implementation. This is because JSON:API module has been added to core in version 8.7. You can see the change record here: https://www.drupal.org/node/3041438

Let's see how to add a field to the response.

There is more that one way to do this, but this time I will show you how to use computed fields to do it. These fields are not stored in the database like regular fields, but they are cached if you have the cache module enabled.

To add a computed field you first have to implement hook_entity_base_field_info_alter() in your .module file like this:

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\MODULE_NAME\Plugin\Field\MyComputedField;

/**
 * Implements hook_entity_base_field_info_alter().
 */
function MODULE_NAME_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() == 'node') {
    $fields['my_computed_field'] = BaseFieldDefinition::create('string')
      ->setLabel(t('My computed field'))
      ->setName('My computed field')
      ->setDescription(t('My computed field description.'))
      ->setComputed(TRUE)
      ->setClass(MyComputedField::class);
  }
}

This adds a computed field called my_computed_field to all nodes. Now, let's add MyComputedField class.

<?php

namespace Drupal\MODULE_NAME\Plugin\Field;

use Drupal\Core\Field\FieldItemList;
use Drupal\Core\TypedData\ComputedItemListTrait;

class MyComputedField extends FieldItemList {

  use ComputedItemListTrait;

  /**
   * Computes the field value.
   */
  protected function computeValue() {
    $this->list[0] = $this->createItem(0, 'My computed field value');
  }

}

This class file is located under MODULE_NAME/src/Plugin/Field directory.

If you clear the cache, you will see your new field in the JSON:API output for node resources.

This also works for RESTful Web Services module that is in Drupal core!

One thing to note is that you cannot add filters on computed fields. This is because filtering in JSON:API module is built directly on top of the core entity query API. And because core doesn't support filtering computed fields, JSON:API is also not supporting that operation.

This might change in the future as you can see in this issue: https://www.drupal.org/project/drupal/issues/2962457 but for now that can't be done.

About author

Goran Nikolovski is a highly experienced Drupal developer with an extensive skill set that includes PHP, MySQL, HTML, CSS and Javascript. He has experience with large Drupal sites and Drupal Commerce 2.x integration, and he is author of several Drupal modules.