function JsonApiDocumentTopLevelNormalizer::getNormalizationSchema

Overrides SchematicNormalizerTrait::getNormalizationSchema

File

core/modules/jsonapi/src/Normalizer/JsonApiDocumentTopLevelNormalizer.php, line 344

Class

JsonApiDocumentTopLevelNormalizer
Normalizes the top-level document according to the JSON:API specification.

Namespace

Drupal\jsonapi\Normalizer

Code

public function getNormalizationSchema(mixed $object, array $context = []) : array {
  // If we are providing a schema based only on an interface, we lack context
  // to provide anything more than a ref to the JSON:API top-level schema.
  $fallbackSchema = [
    '$ref' => JsonApiSpec::SUPPORTED_SPECIFICATION_JSON_SCHEMA,
  ];
  if (is_string($object)) {
    return $fallbackSchema;
  }
  assert($object instanceof JsonApiDocumentTopLevel);
  if ($object->getData() instanceof OmittedData) {
    // A top-level omitted data object is a bit weird but it will only contain
    // information in the 'links' property, so we can fall back.
    return $fallbackSchema;
  }
  $schema = [
    'allOf' => [
      [
        '$ref' => JsonApiSpec::SUPPORTED_SPECIFICATION_JSON_SCHEMA,
      ],
    ],
  ];
  // Top-level JSON:API documents may contain top-level data or an error
  // collection.
  $data = $object->getData();
  if ($data instanceof ErrorCollection) {
    // There's not much else to state here, because errors are a known schema.
    $schema['required'] = [
      'errors',
    ];
  }
  // Relationship data - "resource identifier object(s)"
  if ($data instanceof RelationshipData) {
    if ($data->getCardinality() === 1) {
      $schema['properties']['data'] = [
        '$ref' => JsonApiSpec::SUPPORTED_SPECIFICATION_JSON_SCHEMA . '#/definitions/relationship',
      ];
    }
    else {
      $schema['properties']['data'] = [
        'type' => 'array',
        'items' => [
          '$ref' => JsonApiSpec::SUPPORTED_SPECIFICATION_JSON_SCHEMA . '#/definitions/relationship',
        ],
        'unevaluatedItems' => FALSE,
      ];
      if ($data->getCardinality() !== FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
        $schema['properties']['data']['maxContains'] = $data->getCardinality();
      }
      // We can't do a minContains with the data available in this context.
    }
  }
  if ($data instanceof IncludedData) {
    if ($data instanceof NullIncludedData) {
      $schema['properties']['included'] = [
        'type' => 'array',
        'maxContains' => 0,
      ];
    }
    else {
      $schema['properties']['included'] = [
        // 'included' member is always an array.
'type' => 'array',
        'items' => [
          'oneOf' => $this->getSchemasForDataCollection($data->getData(), $context),
        ],
      ];
    }
  }
  if ($data instanceof ResourceObjectData) {
    if ($data->getCardinality() === 1) {
      assert($data->count() === 1);
      $schema['properties']['data'] = [
        'oneOf' => [
          $this->getSchemasForDataCollection($data->getData(), $context),
          [
            'type' => 'null',
          ],
        ],
      ];
    }
    else {
      $schema['properties']['data'] = [
        'type' => 'array',
        'items' => [
          'oneOf' => $this->getSchemasForDataCollection($data->getData(), $context),
        ],
      ];
      if ($data->getCardinality() !== FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
        $schema['properties']['data']['maxContains'] = $data->getCardinality();
      }
    }
  }
  return $schema;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.