logo

Extra Block Types (EBT) - Nieuwe Layout Builder ervaringā—

Extra Block Types (EBT) - gestileerde, aanpasbare bloktypes: Slideshows, Tabs, Cards, Accordions en vele andere. Ingebouwde instellingen voor achtergrond, DOM Box, javascript-plugins. Ervaar vandaag al de toekomst van layout building.

Demo EBT-modules Download EBT-modules

ā—Extra Paragraph Types (EPT) - Nieuwe Paragraphs ervaring

Extra Paragraph Types (EPT) - analoge op paragrafen gebaseerde set modules.

Demo EPT-modules Download EPT-modules

Scroll
04/09/2025, by Ivan

JSON:API heeft veel concepten in de specificatie, die hier niet allemaal gedocumenteerd zijn. Gebruikers van de module hoeven echter niet alle concepten van de specificatie volledig te begrijpen om productief te kunnen werken met deze module. Als je wĆ©l dieper wilt ingaan op hoe de documenten van JSON:API zijn opgebouwd, waarom de module iets op een bepaalde manier doet, of gewoon meer wilt leren over het ontwerp van de module, dan worden lezers aangemoedigd om de specificatie te lezen op jsonapi.org.

Documentstructuur

JSON:API is zeer uitgesproken over hoe JSON-documenten moeten worden opgebouwd en welke informatie in elk request- en/of response-body moet staan.

Elk request/response-body moet onder ƩƩn enkel JSON-object vallen.

{
   // je data hier...
}

De data, of de informatie die specifiek is voor een resource of meerdere resources, moet binnen dit top-level object leven onder het data ā€œmemberā€. Een ā€œmemberā€ is gewoon een vooraf gedefinieerde key in het JSON-object. Het data member kan ofwel een object ({}) zijn of een array ([]). Bij het aanmaken of bijwerken van een resource zal dit altijd een enkel object ({}) zijn dat een enkel item voorstelt. Alleen bij het ophalen van een ā€œcollectieā€ van meerdere resources zal deze property een array zijn.

{
  "data": {
    // Je resource data komt hier.
  }
}

Andere top-level members zijn: errorsmetalinks, en included. Hiervan zal included het vaakst worden gebruikt, maar dit wordt later in de documentatie behandeld.

Voor meer informatie over de top-level structuur kun je de specificatie raadplegen.

Binnen de data- en included-members staan ā€œresource objectsā€ of ā€œresource identifier objectsā€. ā€œResource objectsā€ vertegenwoordigen de inhoud van de resources (entiteiten) waar je mee werkt. ā€œResource identifier objectsā€ zijn zoals foreign keys in een database; ze identificeren een resource zonder de velden van die resource te bevatten. In Drupal-termen is een resource object meestal de JSON-representatie van een enkele entiteit, dat kan een node zijn, een taxonomieterm of een gebruiker. In Drupal-termen is een resource identifier gewoon genoeg informatie om een entiteit te laden—je hebt het type en het ID, en niets meer.

Elk resource object moet twee members bevatten: type en id. De enige uitzondering hierop is bij het aanmaken van een nieuwe entiteit, in dat geval mag het id worden weggelaten om Drupal een id te laten genereren voor de nieuwe resource. Het is echter volledig mogelijk dat de clientapplicatie een UUID aan de resource meegeeft bij het aanmaken van een nieuwe entiteit. Alle ID’s in JSON:API zijn UUID’s.

Het type member is altijd verplicht. De waarde voor het type-member is afgeleid van de naam van het entiteitstype en de bundle, waar van toepassing. Het type voor een entiteitsresource volgt altijd het patroon entity_type--bundle. Bijvoorbeeld: de core node-typen article en basic page worden weergegeven als: node--article en node--page.

Dus, op een entiteit zonder verplichte eigenschappen of velden, kan men een nieuwe entiteit aanmaken met de volgende JSON:

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

Dit zou echter niet erg nuttig zijn. We moeten echte waarden voor de entiteit opnemen. Om dit te doen heeft JSON:API twee members voor waarden: attributes en relationshipsattributes slaan waarden op die specifiek zijn voor de onderliggende resource. relationships zijn waarden die behoren tot een andere resource in het systeem. In Drupal-termen vertegenwoordigen relationships meestal waarden die worden opgeslagen door een entiteitsreferentie. Op de core article-bundle van Drupal kan dit de uid property zijn. Dit komt omdat de uid property een entiteitsreferentie is naar de gebruiker die het artikel heeft geschreven. De body van een document met attributes en relationships kan er zo uitzien:

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

Zoals je ziet staat de uid property onder het relationships-member. Net als de hoofdresource bevat het ook een type- en een id-member, omdat het een aparte en afzonderlijke resource is.

Merk op dat uid geen attributes of relationships heeft. Dit komt omdat JSON:API de inhoud van een relatie niet opneemt tenzij hier expliciet om gevraagd wordt via een speciale queryparameter, include. Meer hierover later in de documentatie (zie ā€œResources ophalen (GET)ā€).

Voor meer details over de structuur van resource objects kun je de specificatie raadplegen.

§ ā€œVirtueleā€ resource-identificatoren

In sommige omstandigheden staat Drupal toe dat een relatie naar een resource verwijst (een entiteitsreferentie naar een entiteit) die niet in de database is opgeslagen en daarom niet via JSON:API kan worden opgehaald. De ā€œvirtueleā€ resource-identificator kan verschillende omstandigheden aanduiden afhankelijk van de context, maar verwijst altijd naar een resource die niet kan worden gevonden.

Gebruik en betekenis van de ā€˜virtuele’ resource-identificator in Drupal core

Het taxonomietermveld parent is het meest opvallende voorbeeld van dit speciale geval in Drupal core. Dit relatieveld kan een resource-identificator bevatten voor een ā€œvirtueleā€ taxonomieterm-resource. In dit geval identificeert de ā€œvirtueleā€ resource-identificator de <root> taxonomieterm. Dit geeft aan dat de verwijzende term zich op het hoogste niveau van zijn vocabulaire bevindt.

Bekijk bijvoorbeeld het volgende response-document voor een hypothetische taxonomieterm:

{
  "data": {
    "type": "taxonomy_term--tags",
    "id": "2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e",
    "attributes": {
      "name": "Politiek"
    },
    "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": "Gebruik en betekenis van de ā€˜virtuele’ resource-identificator."
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Merk op dat de parent-relatie van deze Term (een entiteitsreferentieveld) een resource identifier object heeft waarvan het id geen UUID is, maar "virtual". Dit is noodzakelijk omdat een top-level of root-level Term een verwijzing heeft naar een niet-opgeslagen <root>-term (target_id = 0) als ouder.

Waarom?

Aangezien de root-term niet wordt opgeslagen en een Term meer dan ƩƩn ouder kan hebben, is de cruciale vraag: hoe onderscheiden we een Term die:

  • alleen Term 3 als ouder heeft ([3]) ?
  • zowel deze niet-opgeslagen root Term als ouder Ć©n een Term 3 ([0, 3]) heeft?

Het antwoord is dat als JSON:API de niet-opgeslagen root-term 0 zou weglaten in plaats van het "virtual"-ID te gebruiken, het niet mogelijk zou zijn die twee gevallen te onderscheiden!

§ ā€œOntbrekendeā€ resource-identificatoren

Drupal ā€œruimtā€ relaties naar verwijderde resources niet op (entiteitsreferentievelden die verwijzingen hebben naar entiteiten die zijn verwijderd). Met andere woorden: Drupal laat ā€œzwevendeā€ relaties (entiteitsreferenties) staan.

Wanneer JSON:API zulke zwevende relaties tegenkomt, gebruikt het de ā€œontbrekendeā€ resource-identificator.

Gebruik en betekenis van de ā€˜ontbrekende’ resource-identificator in Drupal core

Blijvend bij het voorbeeld van de ā€˜virtuele’ resource-identificator: het taxonomietermveld parent. Stel dat een bepaalde taxonomieterm vroeger de taxonomieterm ā€œBelgiĆ«ā€ als ouder had, maar dat de resource van de taxonomieterm ā€œBelgiĆ«ā€ nu niet meer bestaat — misschien omdat het kleine land BelgiĆ« ophield te bestaan. Dan zou dit relatieveld een resource-identificator bevatten voor een ā€œontbrekendeā€ taxonomieterm-resource.

Bekijk bijvoorbeeld het volgende response-document voor een hypothetische taxonomieterm:

{
  "data": {
    "type": "taxonomy_term--tags",
    "id": "2ee9f0ef-1b25-4bbe-a00f-8649c68b1f7e",
    "attributes": {
      "name": "Politiek"
    },
    "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": "Gebruik en betekenis van de ā€˜ontbrekende’ resource-identificator."
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Merk op dat de parent-relatie van deze Term (een entiteitsreferentieveld) een resource identifier object heeft waarvan het id geen UUID is, maar "missing". Bovendien is het type unknown (omdat Drupal de bundle van de verwezen entiteit niet opslaat, alleen het entiteitstype, en dus het bepalen van de JSON:API-resource-typenaam onmogelijk is).

Artikel uit de Drupal-documentatie.