Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll
20/04/2025, by Ivan

JSON:API содержит множество концепций в своей спецификации, но не все из них задокументированы здесь. Тем не менее, пользователям модуля не нужно полностью понимать все концепции спецификации, чтобы продуктивно использовать модуль. Если вы хотите глубже разобраться в том, как устроены документы JSON:API, почему модуль работает тем или иным образом, или просто хотите больше узнать о дизайне модуля, рекомендуется ознакомиться со спецификацией на сайте jsonapi.org.

Структура документа

JSON:API строго определяет, как должны быть структурированы JSON-документы и какую информацию необходимо включать в каждое тело запроса и/или ответа.

Каждое тело запроса/ответа должно быть объектом JSON верхнего уровня.

{
   // ваши данные здесь...
}

Данные, или информация, относящаяся к ресурсу или ресурсам, должны находиться внутри этого объекта верхнего уровня под "элементом" с ключом data. Элемент — это просто предопределённый ключ в объекте JSON. Элемент data может быть либо объектом ({}), либо массивом ([]). При создании или обновлении ресурса это всегда будет одиночный объект ({}), представляющий один элемент. Только при получении "коллекции" нескольких ресурсов это свойство будет массивом.

{
  "data": {
    // Данные вашего ресурса здесь.
  }
}

Другие элементы верхнего уровня включают: errorsmetalinks и included. Из них чаще всего используется included, но он будет рассмотрен позже в документации.

Для получения дополнительной информации о структуре верхнего уровня можно обратиться к спецификации.

Внутри элементов data и included находятся "объекты ресурсов" или "объекты идентификаторов ресурсов". "Объекты ресурсов" представляют собой содержимое ресурсов (сущностей), с которыми вы будете работать. "Объекты идентификаторов ресурсов" подобны внешним ключам в базе данных; они идентифицируют ресурс, не включая в себя его поля. В терминах Drupal, объект ресурса — это, как правило, JSON-представление одной сущности: узла, термина таксономии или пользователя. Снова в терминах Drupal, идентификатор ресурса содержит достаточно информации, чтобы загрузить сущность — его тип и ID, и ничего больше.

Каждый объект ресурса обязан содержать два элемента: type и id. Единственное исключение — при создании новой сущности, в этом случае id можно опустить, чтобы позволить Drupal сгенерировать его. Однако клиентское приложение вполне может предоставить UUID ресурса при создании. Все ID в JSON:API являются UUID.

Элемент type всегда обязателен. Значение для типа формируется из имени типа сущности и её подтипа (bundle), если применимо. Тип для ресурса всегда следует шаблону entity_type--bundle. Например, для основных типов узлов article и basic page это будут: node--article и node--page.

Таким образом, для сущности без обязательных полей можно создать новый объект с таким JSON:

{
  "data": {
    "type": "node--my-bundle",
  }
}

Однако это было бы не очень полезно. Нам нужно включить фактические значения для сущности. Для этого JSON:API использует два элемента: attributes и relationships. attributes содержит значения, специфичные для самой сущности. relationships — это значения, которые принадлежат другим ресурсам. В Drupal, relationships обычно обозначает поля-ссылки на сущности. Например, в типе статьи свойство uid — это ссылка на пользователя, который написал статью. Пример тела документа с attributes и relationships может выглядеть так:

{
  "data": {
    "type": "node--my-bundle",
    "id": "2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e",
    "attributes": {
      "title": "Пример"
    },
    "relationships": {
      "uid": {
        "data": {
          "type": "user--user",
          "id": "53bb14cc-544a-4cf2-88e8-e9cdd0b6948f"
        }
      }
    }
  }
}

Как видите, свойство uid находится под элементом relationships. Как и основной ресурс, оно содержит type и id, так как это отдельный и самостоятельный ресурс.

Обратите внимание, что у uid нет элементов attributes или relationships. Это потому, что JSON:API не включает содержимое связанного ресурса, если явно не запрошено с помощью специального параметра запроса include. Подробнее об этом далее в документации (см. "Получение ресурсов (GET)").

Подробнее о структуре объектов ресурсов можно узнать в спецификации.

§ «Виртуальные» идентификаторы ресурсов

В некоторых случаях Drupal позволяет связям ссылаться на ресурс (поле-ссылка на сущность), который не хранится в базе данных и, следовательно, недоступен через JSON:API. «Виртуальный» идентификатор ресурса может означать разные ситуации в зависимости от контекста, но всегда относится к ресурсу, который не может быть найден.

Использование и значение 'виртуального' идентификатора ресурса в ядре Drupal

Поле parent термина таксономии — самый примечательный пример этого особого случая. Это поле может содержать идентификатор ресурса для «виртуального» термина. В таком случае он указывает на термин <root>, что сигнализирует о том, что данный термин находится на верхнем уровне иерархии словаря.

Пример ответа для гипотетического термина таксономии:

{
  "data": {
    "type": "taxonomy_term--tags",
    "id": "2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e",
    "attributes": {
      "name": "Политика"
    },
    "relationships": {
      "parent": {
        "data": [
          {
            "id": "virtual",
            "type": "taxonomy_term--tags",
            "meta": {
              "links": {
                "help": {
                  "href": "https://www.drupal.org/docs/8/modules/json-api/core-concepts#virtual",
                  "meta": {
                    "about": "Использование и значение 'виртуального' идентификатора ресурса."
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Обратите внимание, что в этом примере свойство parent имеет объект идентификатора ресурса, где id не UUID, а "virtual". Это необходимо, потому что термин верхнего уровня ссылается на нестандартный термин <root> (target_id = 0).

Почему?

Поскольку корневой термин не хранится и один термин может иметь нескольких родителей, возникает важный вопрос: как отличить ситуацию, когда термин:

  • имеет только термин 3 как родителя ([3])?
  • имеет и корневой термин 0, и термин 3 как родителей ([0, 3])?

Ответ: если бы JSON:API опустил нестандартный корневой термин 0, а не использовал ID "virtual", тогда невозможно было бы различить эти два случая!

§ «Отсутствующие» идентификаторы ресурсов

Drupal не «очищает» связи, ведущие к удалённым сущностям (поля-ссылки на сущности, которые были удалены). Иными словами: Drupal оставляет «висячие» ссылки без изменений.

Когда JSON:API сталкивается с такими ссылками, он использует идентификатор ресурса "missing".

Использование и значение 'отсутствующего' идентификатора ресурса в ядре Drupal

Оставаясь в контексте поля parent термина таксономии: представим, что данный термин ранее имел родителем термин «Бельгия», но теперь он удалён — возможно, страна Бельгия прекратила своё существование. Тогда это поле будет содержать идентификатор ресурса для «отсутствующего» термина.

Пример ответа для гипотетического термина:

{
  "data": {
    "type": "taxonomy_term--tags",
    "id": "2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e",
    "attributes": {
      "name": "Политика"
    },
    "relationships": {
      "parent": {
        "data": [
          {
            "id": "missing",
            "type": "unknown",
            "meta": {
              "links": {
                "help": {
                  "href": "https://www.drupal.org/docs/8/modules/json-api/core-concepts#missing",
                  "meta": {
                    "about": "Использование и значение 'отсутствующего' идентификатора ресурса."
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Обратите внимание, что свойство parent имеет идентификатор ресурса, где id — это "missing", а typeunknown (поскольку Drupal не хранит bundle удалённой сущности, невозможно определить имя ресурса в терминах JSON:API).

Статья с сайта Drupal Documentation.