diff --git a/jsonapi.services.yml b/jsonapi.services.yml
index 24af943..5b4c023 100644
--- a/jsonapi.services.yml
+++ b/jsonapi.services.yml
@@ -1,9 +1,7 @@
 services:
   serializer.normalizer.entity_reference_item.jsonapi:
-    class: Drupal\jsonapi\Normalizer\EntityReferenceItemNormalizer
-    arguments: ['@jsonapi.resource.manager']
-    calls:
-      - [setContainer, ['@service_container']]
+    class: Drupal\jsonapi\Normalizer\RelationshipItemNormalizer
+    arguments: ['@jsonapi.resource.manager', '@serializer.normalizer.document_root.jsonapi',]
     tags:
       - { name: normalizer, priority: 21 }
   serializer.normalizer.field_item.jsonapi:
@@ -20,9 +18,14 @@ services:
       - { name: normalizer, priority: 21 }
   serializer.normalizer.entity_reference_field.jsonapi:
     class: Drupal\jsonapi\Normalizer\EntityReferenceFieldNormalizer
+    arguments: ['@jsonapi.link_manager', '@entity_field.manager', '@plugin.manager.field.field_type', '@jsonapi.resource.manager']
     tags:
       - { name: normalizer, priority: 31 }
-    arguments: ['@jsonapi.link_manager', '@entity_field.manager', '@plugin.manager.field.field_type', '@jsonapi.resource.manager']
+  serializer.normalizer.relationship.jsonapi:
+    class: Drupal\jsonapi\Normalizer\RelationshipNormalizer
+    arguments: ['@jsonapi.resource.manager', '@serializer.normalizer.document_root.jsonapi', '@jsonapi.link_manager']
+    tags:
+      - { name: normalizer, priority: 21 }
   serializer.normalizer.entity.jsonapi:
     class: Drupal\jsonapi\Normalizer\ContentEntityNormalizer
     arguments: ['@jsonapi.link_manager', '@jsonapi.current_context']
diff --git a/src/Configuration/ResourceManager.php b/src/Configuration/ResourceManager.php
index 64fb6ed..678a418 100644
--- a/src/Configuration/ResourceManager.php
+++ b/src/Configuration/ResourceManager.php
@@ -66,13 +66,6 @@ class ResourceManager implements ResourceManagerInterface {
       return $this->all;
     }
     $entity_type_ids = array_keys($this->entityTypeManager->getDefinitions());
-    $this->all = array_map(function ($entity_type_id) {
-      $resource_config = new ResourceConfig($this->configFactory, $this->entityTypeManager);
-      $resource_config->setEntityTypeId($entity_type_id);
-      $resource_config->setPath(sprintf('/%s', $entity_type_id));
-      $resource_config->setTypeName(sprintf('%s', $entity_type_id));
-      return $resource_config;
-    }, $entity_type_ids);
     foreach ($entity_type_ids as $entity_type_id) {
       // Add a ResourceConfig per bundle.
       $this->all = array_merge($this->all, array_map(function ($bundle) use ($entity_type_id) {
diff --git a/src/Normalizer/ConfigEntityNormalizer.php b/src/Normalizer/ConfigEntityNormalizer.php
index be8494f..c6f5e88 100644
--- a/src/Normalizer/ConfigEntityNormalizer.php
+++ b/src/Normalizer/ConfigEntityNormalizer.php
@@ -3,6 +3,7 @@
 namespace Drupal\jsonapi\Normalizer;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\jsonapi\RelationshipInterface;
 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 
 /**
@@ -12,7 +13,7 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
  *
  * @package Drupal\jsonapi\Normalizer
  */
-class ConfigEntityNormalizer extends ContentEntityNormalizer {
+class ConfigEntityNormalizer extends EntityNormalizer {
 
   /**
    * The interface or class that this Normalizer supports.
@@ -22,35 +23,21 @@ class ConfigEntityNormalizer extends ContentEntityNormalizer {
   protected $supportedInterfaceOrClass = ConfigEntityInterface::class;
 
   /**
-   * Gets the field names for the given entity.
-   *
-   * @param mixed $entity
-   *   The entity.
-   *
-   * @return array
-   *   The fields.
+   * {@inheritdoc}
    */
-  protected function getFields($entity) {
+  protected function getFields($entity, $bundle_id) {
     /* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
     return $entity->toArray();
   }
 
   /**
-   * Serializes a given field.
-   *
-   * @param mixed $field
-   *   The field to serialize.
-   * @param array $context
-   *   The normalization context.
-   * @param string $format
-   *   The serialization format.
-   *
-   * @return Value\FieldNormalizerValueInterface
-   *   The normalized value.
+   * {@inheritdoc}
    */
   protected function serializeField($field, $context, $format) {
     $output = $this->serializer->normalize($field, $format, $context);
-    $output->setPropertyType('attributes');
+    $field instanceof RelationshipInterface ?
+      $output->setPropertyType('relationships') :
+      $output->setPropertyType('attributes');
     return $output;
   }
 
diff --git a/src/Normalizer/ContentEntityNormalizer.php b/src/Normalizer/ContentEntityNormalizer.php
index 1c0b7c1..92b6c29 100644
--- a/src/Normalizer/ContentEntityNormalizer.php
+++ b/src/Normalizer/ContentEntityNormalizer.php
@@ -2,195 +2,19 @@
 
 namespace Drupal\jsonapi\Normalizer;
 
+use Drupal\Core\Access\AccessibleInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Field\EntityReferenceFieldItemList;
-use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\jsonapi\Configuration\ResourceConfigInterface;
 use Drupal\jsonapi\Context\CurrentContextInterface;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+use Drupal\jsonapi\RelationshipInterface;
 use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
 
 /**
- * Converts the Drupal entity object structure to a HAL array structure.
+ * Converts the Drupal content entity object structure to a HAL array structure.
  */
-class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInterface, ContentEntityNormalizerInterface {
-
-  /**
-   * The interface or class that this Normalizer supports.
-   *
-   * @var string
-   */
-  protected $supportedInterfaceOrClass = ContentEntityInterface::class;
-
-  /**
-   * The formats that the Normalizer can handle.
-   *
-   * @var array
-   */
-  protected $formats = array('api_json');
-
-  /**
-   * The link manager.
-   *
-   * @var \Drupal\jsonapi\LinkManager\LinkManagerInterface
-   */
-  protected $linkManager;
-
-  /**
-   * The resource manager.
-   *
-   * @var \Drupal\jsonapi\Configuration\ResourceManagerInterface
-   */
-  protected $resourceManager;
-
-  /**
-   * The current JSON API request context.
-   *
-   * @var \Drupal\jsonapi\Context\CurrentContextInterface
-   */
-  protected $currentContext;
-
-  /**
-   * Constructs an ContentEntityNormalizer object.
-   *
-   * @param \Drupal\jsonapi\LinkManager\LinkManagerInterface $link_manager
-   *   The link manager.
-   * @param \Drupal\jsonapi\Context\CurrentContextInterface $current_context
-   *   The current context.
-   */
-  public function __construct(LinkManagerInterface $link_manager, CurrentContextInterface $current_context) {
-    $this->linkManager = $link_manager;
-    $this->currentContext = $current_context;
-    $this->resourceManager = $current_context->getResourceManager();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function normalize($entity, $format = NULL, array $context = array()) {
-    // If the fields to use were specified, only output those field values.
-    $resource_type = $context['resource_config']->getTypeName();
-    if (!empty($context['sparse_fieldset'][$resource_type])) {
-      $field_names = $context['sparse_fieldset'][$resource_type];
-    }
-    else {
-      $field_names = $this->getFieldNames($entity);
-    }
-    /* @var Value\FieldNormalizerValueInterface[] $normalizer_values */
-    $normalizer_values = [];
-    foreach ($this->getFields($entity) as $field_name => $field) {
-      // Relationships cannot be excluded by using sparse fieldsets.
-      $is_relationship = $this->isRelationship($field);
-      if (!$is_relationship && !in_array($field_name, $field_names)) {
-        continue;
-      }
-      $normalizer_values[$field_name] = $this->serializeField($field, $context, $format);
-    }
-    // Clean all the NULL values coming from denied access.
-    $normalizer_values = array_filter($normalizer_values);
-
-    $link_context = ['link_manager' => $this->linkManager];
-    return new Value\ContentEntityNormalizerValue($normalizer_values, $context, $entity, $link_context);
-  }
-
-  /**
-   * Checks if the passed field is a relationship field.
-   *
-   * @param mixed $field
-   *   The field.
-   *
-   * @return bool
-   *   TRUE if it's a JSON API relationship.
-   */
-  protected function isRelationship($field) {
-    return $field instanceof EntityReferenceFieldItemList;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function denormalize($data, $class, $format = NULL, array $context = array()) {
-    if (empty($context['resource_config']) || !$context['resource_config'] instanceof ResourceConfigInterface) {
-      throw new PreconditionFailedHttpException('Missing context during denormalization.');
-    }
-    /* @var \Drupal\jsonapi\Configuration\ResourceConfigInterface $resource_config */
-    $resource_config = $context['resource_config'];
-    $bundle_id = $resource_config->getBundleId();
-    $bundle_key = $this->resourceManager
-      ->getEntityTypeManager()
-      ->getDefinition($resource_config->getEntityTypeId())
-      ->getKey('bundle');
-    if ($bundle_key && $bundle_id) {
-      $data[$bundle_key] = $bundle_id;
-    }
-
-    return $resource_config->getStorage()->create($data);
-  }
-
-  /**
-   * Gets the field names for the given entity.
-   *
-   * @param mixed $entity
-   *   The entity.
-   *
-   * @return string[]
-   *   The field names.
-   */
-  protected function getFieldNames($entity) {
-    /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    return array_keys($this->getFields($entity));
-  }
-
-  /**
-   * Gets the field names for the given entity.
-   *
-   * @param mixed $entity
-   *   The entity.
-   *
-   * @return array
-   *   The fields.
-   */
-  protected function getFields($entity) {
-    /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    $fields = $entity->getFields();
-    if (!$this->currentContext->getResourceConfig()->getBundleId()) {
-      // If this request if for the base entity, then strip all fields attached to a specific bundles. That way all the
-      // entity requests will look the same regardless of their bundle. If you need the information about the fields
-      // attached to the bundle, you can request the whole entity by using the bundle resource. As a shortcut, all
-      // entity resources contain a fake relationship to the bundle specific resource.
-      $fields = array_filter($fields, function (FieldItemListInterface $field) {
-        return (bool) !$field->getDataDefinition()->getTargetBundle();
-      });
-    }
-    return $fields;
-  }
-
-
-  /**
-   * Serializes a given field.
-   *
-   * @param mixed $field
-   *   The field to serialize.
-   * @param array $context
-   *   The normalization context.
-   * @param string $format
-   *   The serialization format.
-   *
-   * @return Value\FieldNormalizerValueInterface
-   *   The normalized value.
-   */
-  protected function serializeField($field, $context, $format) {
-    /* @var \Drupal\Core\Field\FieldItemListInterface $field */
-    // Continue if the current user does not have access to view this field.
-    if (!$field->access('view', $context['account'])) {
-      return NULL;
-    }
-    $output = $this->serializer->normalize($field, $format, $context);
-    $is_relationship = $this->isRelationship($field);
-    $property_type = $is_relationship ? 'relationships' : 'attributes';
-    $output->setPropertyType($property_type);
-    return $output;
-  }
+class ContentEntityNormalizer extends EntityNormalizer {
 
 }
diff --git a/src/Normalizer/DocumentRootNormalizer.php b/src/Normalizer/DocumentRootNormalizer.php
index e378931..d87cd78 100644
--- a/src/Normalizer/DocumentRootNormalizer.php
+++ b/src/Normalizer/DocumentRootNormalizer.php
@@ -9,13 +9,14 @@ use Drupal\jsonapi\Resource\DocumentWrapperInterface;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 
 /**
  * Class DocumentRootNormalizer.
  *
  * @package Drupal\jsonapi\Normalizer
  */
-class DocumentRootNormalizer extends NormalizerBase implements DenormalizerInterface, DocumentRootNormalizerInterface {
+class DocumentRootNormalizer extends NormalizerBase implements DenormalizerInterface, NormalizerInterface, DocumentRootNormalizerInterface {
 
   /**
    * The interface or class that this Normalizer supports.
diff --git a/src/Normalizer/DocumentRootNormalizerInterface.php b/src/Normalizer/DocumentRootNormalizerInterface.php
index c0221fe..40dba31 100644
--- a/src/Normalizer/DocumentRootNormalizerInterface.php
+++ b/src/Normalizer/DocumentRootNormalizerInterface.php
@@ -8,4 +8,14 @@ namespace Drupal\jsonapi\Normalizer;
  *
  * @package Drupal\jsonapi\Normalizer
  */
-interface DocumentRootNormalizerInterface {}
+interface DocumentRootNormalizerInterface {
+
+  /**
+   * Build the normalizer value.
+   *
+   * @return \Drupal\jsonapi\Normalizer\Value\ContentEntityNormalizerValueInterface
+   *   The normalizer value.
+   */
+  public function buildNormalizerValue($data, $format = NULL, array $context = array());
+
+}
diff --git a/src/Normalizer/ContentEntityNormalizer.php b/src/Normalizer/EntityNormalizer.php
similarity index 79%
copy from src/Normalizer/ContentEntityNormalizer.php
copy to src/Normalizer/EntityNormalizer.php
index 1c0b7c1..7e91ad6 100644
--- a/src/Normalizer/ContentEntityNormalizer.php
+++ b/src/Normalizer/EntityNormalizer.php
@@ -2,19 +2,20 @@
 
 namespace Drupal\jsonapi\Normalizer;
 
+use Drupal\Core\Access\AccessibleInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Field\EntityReferenceFieldItemList;
-use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\jsonapi\Configuration\ResourceConfigInterface;
 use Drupal\jsonapi\Context\CurrentContextInterface;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+use Drupal\jsonapi\RelationshipInterface;
 use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
 
 /**
  * Converts the Drupal entity object structure to a HAL array structure.
  */
-class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInterface, ContentEntityNormalizerInterface {
+class EntityNormalizer extends NormalizerBase implements DenormalizerInterface, ContentEntityNormalizerInterface {
 
   /**
    * The interface or class that this Normalizer supports.
@@ -71,15 +72,18 @@ class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInte
   public function normalize($entity, $format = NULL, array $context = array()) {
     // If the fields to use were specified, only output those field values.
     $resource_type = $context['resource_config']->getTypeName();
+    // Get the bundle ID of the requested resource. This is used to determine if
+    // this is a bundle level resource or an entity level resource.
+    $bundle_id = $context['resource_config']->getBundleId();
     if (!empty($context['sparse_fieldset'][$resource_type])) {
       $field_names = $context['sparse_fieldset'][$resource_type];
     }
     else {
-      $field_names = $this->getFieldNames($entity);
+      $field_names = $this->getFieldNames($entity, $bundle_id);
     }
     /* @var Value\FieldNormalizerValueInterface[] $normalizer_values */
     $normalizer_values = [];
-    foreach ($this->getFields($entity) as $field_name => $field) {
+    foreach ($this->getFields($entity, $bundle_id) as $field_name => $field) {
       // Relationships cannot be excluded by using sparse fieldsets.
       $is_relationship = $this->isRelationship($field);
       if (!$is_relationship && !in_array($field_name, $field_names)) {
@@ -104,7 +108,7 @@ class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInte
    *   TRUE if it's a JSON API relationship.
    */
   protected function isRelationship($field) {
-    return $field instanceof EntityReferenceFieldItemList;
+    return $field instanceof EntityReferenceFieldItemList || $field instanceof RelationshipInterface;
   }
 
   /**
@@ -137,9 +141,9 @@ class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInte
    * @return string[]
    *   The field names.
    */
-  protected function getFieldNames($entity) {
+  protected function getFieldNames($entity, $bundle_id) {
     /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    return array_keys($this->getFields($entity));
+    return array_keys($this->getFields($entity, $bundle_id));
   }
 
   /**
@@ -147,26 +151,17 @@ class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInte
    *
    * @param mixed $entity
    *   The entity.
+   * @param string $bundle_id
+   *   The bundle id.
    *
    * @return array
    *   The fields.
    */
-  protected function getFields($entity) {
+  protected function getFields($entity, $bundle_id) {
     /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    $fields = $entity->getFields();
-    if (!$this->currentContext->getResourceConfig()->getBundleId()) {
-      // If this request if for the base entity, then strip all fields attached to a specific bundles. That way all the
-      // entity requests will look the same regardless of their bundle. If you need the information about the fields
-      // attached to the bundle, you can request the whole entity by using the bundle resource. As a shortcut, all
-      // entity resources contain a fake relationship to the bundle specific resource.
-      $fields = array_filter($fields, function (FieldItemListInterface $field) {
-        return (bool) !$field->getDataDefinition()->getTargetBundle();
-      });
-    }
-    return $fields;
+    return $entity->getFields();
   }
 
-
   /**
    * Serializes a given field.
    *
@@ -181,9 +176,9 @@ class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInte
    *   The normalized value.
    */
   protected function serializeField($field, $context, $format) {
-    /* @var \Drupal\Core\Field\FieldItemListInterface $field */
+    /* @var \Drupal\Core\Field\FieldItemListInterface|\Drupal\jsonapi\RelationshipInterface $field */
     // Continue if the current user does not have access to view this field.
-    if (!$field->access('view', $context['account'])) {
+    if ($field instanceof AccessibleInterface && !$field->access('view', $context['account'])) {
       return NULL;
     }
     $output = $this->serializer->normalize($field, $format, $context);
diff --git a/src/Normalizer/EntityReferenceFieldNormalizer.php b/src/Normalizer/EntityReferenceFieldNormalizer.php
index c318fa6..8604332 100644
--- a/src/Normalizer/EntityReferenceFieldNormalizer.php
+++ b/src/Normalizer/EntityReferenceFieldNormalizer.php
@@ -8,7 +8,9 @@ use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
 use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
 use Drupal\jsonapi\Configuration\ResourceManagerInterface;
+use Drupal\jsonapi\EntityCollection;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+use Drupal\jsonapi\Relationship;
 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
 
@@ -65,37 +67,22 @@ class EntityReferenceFieldNormalizer extends FieldNormalizer implements Denormal
   }
 
   /**
-   * Helper function to normalize field items.
-   *
-   * @param \Drupal\Core\Field\FieldItemListInterface $field
-   *   The field object.
-   * @param string $format
-   *   The format.
-   * @param array $context
-   *   The context array.
-   *
-   * @return array
-   *   The array of normalized field items.
+   * {@inheritdoc}
    */
-  protected function normalizeFieldItems(FieldItemListInterface $field, $format, $context) {
-    $normalizer_items = array();
-    if (!$field->isEmpty()) {
-      foreach ($field as $field_item) {
-        $normalizer_items[] = $this->serializer->normalize($field_item, $format, $context);
-      }
-    }
+  public function normalize($field, $format = NULL, array $context = array()) {
+    /* @var $field \Drupal\Core\Field\FieldItemListInterface */
+    // Build the relationship object based on the Entity Reference and normalize
+    // that object instead.
+    $main_property = $field->getItemDefinition()->getMainPropertyName();
     $definition = $field->getFieldDefinition();
     $cardinality = $definition
       ->getFieldStorageDefinition()
       ->getCardinality();
-    $link_context = [
-      'host_entity_id' => $context['resource_config']->getIdKey() == 'uuid' ? $field->getEntity()->uuid() : $field->getEntity()->id(),
-      'field_name' => $definition->getName(),
-      'link_manager' => $this->linkManager,
-      'resource_config' => $context['resource_config'],
-      'host_uuid' => $field->getEntity()->uuid(),
-    ];
-    return new Value\EntityReferenceNormalizerValue($normalizer_items, $cardinality, $link_context);
+    $entity_collection = new EntityCollection(array_map(function ($item) {
+      return $item->get('entity')->getValue();
+    }, (array) $field->getIterator()));
+    $relationship = new Relationship($this->resourceManager, $field->getName(), $cardinality, $entity_collection, $field->getEntity(), $main_property);
+    return $this->serializer->normalize($relationship, $format, $context);
   }
 
   /**
diff --git a/src/Normalizer/FieldNormalizer.php b/src/Normalizer/FieldNormalizer.php
index 4b1c292..6bb59db 100644
--- a/src/Normalizer/FieldNormalizer.php
+++ b/src/Normalizer/FieldNormalizer.php
@@ -54,7 +54,6 @@ class FieldNormalizer extends NormalizerBase {
    */
   protected function normalizeFieldItems(FieldItemListInterface $field, $format, $context) {
     $normalizer_items = array();
-    $includes = [];
     if (!$field->isEmpty()) {
       foreach ($field as $field_item) {
         $normalizer_items[] = $this->serializer->normalize($field_item, $format, $context);
diff --git a/src/Normalizer/EntityReferenceItemNormalizer.php b/src/Normalizer/RelationshipItemNormalizer.php
similarity index 61%
rename from src/Normalizer/EntityReferenceItemNormalizer.php
rename to src/Normalizer/RelationshipItemNormalizer.php
index 8c5daea..b5d06f2 100644
--- a/src/Normalizer/EntityReferenceItemNormalizer.php
+++ b/src/Normalizer/RelationshipItemNormalizer.php
@@ -5,22 +5,21 @@ namespace Drupal\jsonapi\Normalizer;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 use Drupal\jsonapi\Configuration\ResourceManagerInterface;
+use Drupal\jsonapi\RelationshipItemInterface;
 use Drupal\serialization\EntityResolver\UuidReferenceInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
 /**
  * Converts the Drupal entity reference item object to HAL array structure.
  */
-class EntityReferenceItemNormalizer extends FieldItemNormalizer implements UuidReferenceInterface {
-
-  use ContainerAwareTrait;
+class RelationshipItemNormalizer extends FieldItemNormalizer implements UuidReferenceInterface {
 
   /**
    * The interface or class that this Normalizer supports.
    *
    * @var string
    */
-  protected $supportedInterfaceOrClass = EntityReferenceItem::class;
+  protected $supportedInterfaceOrClass = RelationshipItemInterface::class;
 
   /**
    * The manager for resource configuration.
@@ -30,48 +29,51 @@ class EntityReferenceItemNormalizer extends FieldItemNormalizer implements UuidR
   protected $resourceManager;
 
   /**
+   * The document normalizer.
+   *
+   * @var \Drupal\jsonapi\Normalizer\DocumentRootNormalizerInterface
+   */
+  protected $documentRootNormalizer;
+
+  /**
    * Instantiates a EntityReferenceItemNormalizer object.
    *
    * @param \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager
    *   The resource manager.
+   * @param \Drupal\jsonapi\Normalizer\DocumentRootNormalizerInterface $document_root_normalizer
+   *   The document root normalizer for the include.
    */
-  public function __construct(ResourceManagerInterface $resource_manager) {
+  public function __construct(ResourceManagerInterface $resource_manager, DocumentRootNormalizerInterface $document_root_normalizer) {
     $this->resourceManager = $resource_manager;
+    $this->documentRootNormalizer = $document_root_normalizer;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function normalize($field_item, $format = NULL, array $context = array()) {
-    /* @var $field_item \Drupal\Core\Field\FieldItemInterface */
-    $target_entity = $field_item->get('entity')->getValue();
-    $main_property = $field_item->mainPropertyName();
-    $resource_config = $this->resourceManager
-      ->get($target_entity->getEntityTypeId(), $target_entity->bundle());
-    if ($resource_config->getIdKey() == 'uuid') {
-      $values = [$main_property => $target_entity->uuid()];
-    }
-    else {
-      $values = $field_item->toArray();
-      $values = [$main_property => $values[$main_property]];
-    }
+  public function normalize($relationship_item, $format = NULL, array $context = array()) {
+    /* @var $relationship_item \Drupal\jsonapi\RelationshipItemInterface */
+    // TODO: We are always loading the referenced entity. Even if it is not
+    // going to be included. That may be a performance issue. We do it because
+    // we need to know the entity type and bundle to load the resource config to
+    // get the type for the relationship item. We need a better way of finding
+    // about this.
+    $target_entity = $relationship_item->getTargetEntity();
+    $values = $relationship_item->getValue();
     if (isset($context['langcode'])) {
       $values['lang'] = $context['langcode'];
     }
-    $normalizer_value = new Value\EntityReferenceItemNormalizerValue(
+    $normalizer_value = new Value\RelationshipItemNormalizerValue(
       $values,
-      $resource_config
-        ->getTypeName()
+      $relationship_item->getTargetResourceConfig()
     );
 
+    $host_field_name = $relationship_item->getParent()->getPropertyName();
     // TODO Only include if the target entity type has the resource enabled.
-    if (!empty($context['include']) && in_array($field_item->getParent()
-        ->getName(), $context['include'])
-    ) {
-      $context = $this->buildSubContext($context, $target_entity, $field_item->getParent()
-        ->getName());
-      $entity_normalizer = $this->container->get('serializer.normalizer.document_root.jsonapi');
-      $normalizer_value->setInclude($entity_normalizer->buildNormalizerValue($target_entity, $format, $context));
+    if (!empty($context['include']) && in_array($host_field_name, $context['include'])) {
+      $context = $this->buildSubContext($context, $target_entity, $host_field_name);
+      $included_normalizer_value = $this->documentRootNormalizer->buildNormalizerValue($target_entity, $format, $context);
+      $normalizer_value->setInclude($included_normalizer_value);
     }
     return $normalizer_value;
   }
diff --git a/src/Normalizer/RelationshipNormalizer.php b/src/Normalizer/RelationshipNormalizer.php
new file mode 100644
index 0000000..ae62446
--- /dev/null
+++ b/src/Normalizer/RelationshipNormalizer.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace Drupal\jsonapi\Normalizer;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\jsonapi\Configuration\ResourceManagerInterface;
+use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+use Drupal\jsonapi\Relationship;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
+
+class RelationshipNormalizer extends NormalizerBase {
+
+  /**
+   * The interface or class that this Normalizer supports.
+   *
+   * @var string
+   */
+  protected $supportedInterfaceOrClass = Relationship::class;
+
+  /**
+   * The formats that the Normalizer can handle.
+   *
+   * @var array
+   */
+  protected $formats = array('api_json');
+
+  /**
+   * The manager for resource configuration.
+   *
+   * @var \Drupal\jsonapi\Configuration\ResourceManagerInterface
+   */
+  protected $resourceManager;
+
+  /**
+   * The link manager.
+   *
+   * @var \Drupal\jsonapi\LinkManager\LinkManagerInterface
+   */
+  protected $linkManager;
+
+  /**
+   * The document normalizer.
+   *
+   * @var \Drupal\jsonapi\Normalizer\DocumentRootNormalizerInterface
+   */
+  protected $documentRootNormalizer;
+
+  /**
+   * RelationshipNormalizer constructor.
+   *
+   * @param \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager
+   *   The resource manager.
+   * @param \Drupal\jsonapi\Normalizer\DocumentRootNormalizerInterface $document_root_normalizer
+   *   The document root normalizer for the include.
+   * @param \Drupal\jsonapi\LinkManager\LinkManagerInterface $link_manager
+   *   The link manager.
+   */
+  public function __construct(ResourceManagerInterface $resource_manager, DocumentRootNormalizerInterface $document_root_normalizer, LinkManagerInterface $link_manager) {
+    $this->resourceManager = $resource_manager;
+    $this->documentRootNormalizer = $document_root_normalizer;
+    $this->linkManager = $link_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function denormalize($data, $class, $format = NULL, array $context = array()) {
+    throw new UnexpectedValueException('Denormalization not implemented for JSON API');
+  }
+
+  /**
+   * Helper function to normalize field items.
+   *
+   * @param \Drupal\jsonapi\RelationshipInterface $relationship
+   *   The field object.
+   * @param string $format
+   *   The format.
+   * @param array $context
+   *   The context array.
+   *
+   * @return array
+   *   The array of normalized field items.
+   */
+  public function normalize($relationship, $format = NULL, array $context = array()) {
+    /* @var \Drupal\jsonapi\RelationshipInterface $relationship */
+    $normalizer_items = array();
+    foreach ($relationship->getItems() as $relationship_item) {
+      $normalizer_items[] = $this->serializer->normalize($relationship_item, $format, $context);
+    }
+    $cardinality = $relationship->getCardinality();
+    $link_context = [
+      'host_entity_id' => $context['resource_config']->getIdKey() == 'uuid' ? $relationship->getHostEntity()->uuid() : $relationship->getHostEntity()->id(),
+      'field_name' => $relationship->getPropertyName(),
+      'link_manager' => $this->linkManager,
+      'resource_config' => $context['resource_config'],
+      'host_uuid' => $relationship->getHostEntity()->uuid(),
+    ];
+    return new Value\RelationshipNormalizerValue($normalizer_items, $cardinality, $link_context);
+  }
+
+  /**
+   * Builds the sub-context for the relationship include.
+   *
+   * @param array $context
+   *   The serialization context.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The related entity.
+   * @param string $host_field_name
+   *   The name of the field reference.
+   *
+   * @return array
+   *   The modified new context.
+   *
+   * @see EntityReferenceItemNormalizer::buildSubContext()
+   * @todo This is duplicated code from the reference item. Reuse code instead.
+   */
+  protected function buildSubContext($context, EntityInterface $entity, $host_field_name) {
+    // Swap out the context for the context of the referenced resource.
+    $context['resource_config'] = $this->resourceManager
+      ->get($entity->getEntityTypeId(), $entity->bundle());
+    // Since we're going one level down the only includes we need are the ones
+    // that apply to this level as well.
+    $include_candidates = array_filter($context['include'], function ($include) use ($host_field_name) {
+      return strpos($include, $host_field_name . '.') === 0;
+    });
+    $context['include'] = array_map(function ($include) use ($host_field_name) {
+      return str_replace($host_field_name . '.', '', $include);
+    }, $include_candidates);
+    return $context;
+  }
+
+}
diff --git a/src/Normalizer/Value/FieldItemNormalizerValue.php b/src/Normalizer/Value/FieldItemNormalizerValue.php
index d43d7d9..f930f71 100644
--- a/src/Normalizer/Value/FieldItemNormalizerValue.php
+++ b/src/Normalizer/Value/FieldItemNormalizerValue.php
@@ -51,7 +51,7 @@ class FieldItemNormalizerValue implements FieldItemNormalizerValueInterface {
   /**
    * {@inheritdoc}
    */
-  public function setInclude(DocumentRootNormalizerValueInterface $include) {
+  public function setInclude(ValueExtractorInterface $include) {
     $this->include = $include;
   }
 
diff --git a/src/Normalizer/Value/FieldItemNormalizerValueInterface.php b/src/Normalizer/Value/FieldItemNormalizerValueInterface.php
index 32f33cd..efe1966 100644
--- a/src/Normalizer/Value/FieldItemNormalizerValueInterface.php
+++ b/src/Normalizer/Value/FieldItemNormalizerValueInterface.php
@@ -12,10 +12,10 @@ interface FieldItemNormalizerValueInterface extends ValueExtractorInterface {
   /**
    * Add an include.
    *
-   * @param DocumentRootNormalizerValueInterface $include
+   * @param ValueExtractorInterface $include
    *   The included entity.
    */
-  public function setInclude(DocumentRootNormalizerValueInterface $include);
+  public function setInclude(ValueExtractorInterface $include);
 
   /**
    * Gets the include.
diff --git a/src/Normalizer/Value/EntityReferenceItemNormalizerValue.php b/src/Normalizer/Value/RelationshipItemNormalizerValue.php
similarity index 78%
rename from src/Normalizer/Value/EntityReferenceItemNormalizerValue.php
rename to src/Normalizer/Value/RelationshipItemNormalizerValue.php
index 45e06a6..a437ff7 100644
--- a/src/Normalizer/Value/EntityReferenceItemNormalizerValue.php
+++ b/src/Normalizer/Value/RelationshipItemNormalizerValue.php
@@ -7,7 +7,7 @@ namespace Drupal\jsonapi\Normalizer\Value;
  *
  * @package Drupal\jsonapi\Normalizer\Value
  */
-class EntityReferenceItemNormalizerValue extends FieldItemNormalizerValue implements EntityReferenceItemNormalizerValueInterface {
+class RelationshipItemNormalizerValue extends FieldItemNormalizerValue implements RelationshipItemNormalizerValueInterface {
 
   /**
    * Resource path.
@@ -22,7 +22,7 @@ class EntityReferenceItemNormalizerValue extends FieldItemNormalizerValue implem
    * @param array $values
    *   The values.
    * @param string $resource
-   *   The resource path of the target entity.
+   *   The resource type of the target entity.
    */
   public function __construct(array $values, $resource) {
     parent::__construct($values);
@@ -37,7 +37,7 @@ class EntityReferenceItemNormalizerValue extends FieldItemNormalizerValue implem
       return $value;
     }
     return [
-      'type' => $this->resource,
+      'type' => $this->resource->getTypeName(),
       'id' => $value,
     ];
   }
diff --git a/src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php b/src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php
similarity index 75%
rename from src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php
rename to src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php
index 1961c83..1655e66 100644
--- a/src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php
+++ b/src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php
@@ -7,7 +7,7 @@ namespace Drupal\jsonapi\Normalizer\Value;
  *
  * @package Drupal\jsonapi\Normalizer\Value
  */
-interface EntityReferenceItemNormalizerValueInterface extends FieldItemNormalizerValueInterface {
+interface RelationshipItemNormalizerValueInterface extends FieldItemNormalizerValueInterface {
 
   /**
    * Sets the resource.
diff --git a/src/Normalizer/Value/EntityReferenceNormalizerValue.php b/src/Normalizer/Value/RelationshipNormalizerValue.php
similarity index 89%
rename from src/Normalizer/Value/EntityReferenceNormalizerValue.php
rename to src/Normalizer/Value/RelationshipNormalizerValue.php
index 0cc43f1..88e8ffa 100644
--- a/src/Normalizer/Value/EntityReferenceNormalizerValue.php
+++ b/src/Normalizer/Value/RelationshipNormalizerValue.php
@@ -7,7 +7,7 @@ namespace Drupal\jsonapi\Normalizer\Value;
  *
  * @package Drupal\jsonapi\Normalizer\Value
  */
-class EntityReferenceNormalizerValue extends FieldNormalizerValue implements EntityReferenceNormalizerValueInterface {
+class RelationshipNormalizerValue extends FieldNormalizerValue implements RelationshipNormalizerValueInterface {
 
   /**
    * The link manager.
@@ -40,7 +40,7 @@ class EntityReferenceNormalizerValue extends FieldNormalizerValue implements Ent
   /**
    * Instantiate a EntityReferenceNormalizerValue object.
    *
-   * @param EntityReferenceItemNormalizerValue[] $values
+   * @param RelationshipItemNormalizerValue[] $values
    *   The normalized result.
    * @param int $cardinality
    *   The number of fields for the field list.
@@ -54,7 +54,7 @@ class EntityReferenceNormalizerValue extends FieldNormalizerValue implements Ent
     $this->linkManager = $link_context['link_manager'];
     $this->resourceConfig = $link_context['resource_config'];
     array_walk($values, function ($field_item_value) {
-      if (!$field_item_value instanceof EntityReferenceItemNormalizerValueInterface) {
+      if (!$field_item_value instanceof RelationshipItemNormalizerValueInterface) {
         throw new \RuntimeException(sprintf('Unexpected normalizer item value for this %s.', get_called_class()));
       }
     });
diff --git a/src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php b/src/Normalizer/Value/RelationshipNormalizerValueInterface.php
similarity index 63%
rename from src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php
rename to src/Normalizer/Value/RelationshipNormalizerValueInterface.php
index cb68951..da0908a 100644
--- a/src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php
+++ b/src/Normalizer/Value/RelationshipNormalizerValueInterface.php
@@ -7,4 +7,4 @@ namespace Drupal\jsonapi\Normalizer\Value;
  *
  * @package Drupal\jsonapi\Normalizer\Value
  */
-interface EntityReferenceNormalizerValueInterface extends FieldNormalizerValueInterface {}
+interface RelationshipNormalizerValueInterface extends FieldNormalizerValueInterface {}
diff --git a/src/Relationship.php b/src/Relationship.php
new file mode 100644
index 0000000..c8350d5
--- /dev/null
+++ b/src/Relationship.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Drupal\jsonapi;
+
+use Drupal\Core\Access\AccessibleInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\jsonapi\Configuration\ResourceManagerInterface;
+
+/**
+ * Class Relationship.
+ *
+ * Use this class to create a relationship in your normalizer without having an entity reference field.
+ *
+ * @package Drupal\jsonapi
+ */
+class Relationship implements RelationshipInterface, AccessibleInterface {
+
+  /**
+   * Cardinality.
+   *
+   * @var int
+   */
+  protected $cardinality;
+
+  /**
+   * The entity that holds the relationship.
+   *
+   * @var \Drupal\Core\Entity\EntityInterface
+   */
+  protected $hostEntity;
+
+  /**
+   * The field name.
+   *
+   * @var string
+   */
+  protected $propertyName;
+
+  /**
+   * The resource manager.
+   *
+   * @var \Drupal\jsonapi\Configuration\ResourceManagerInterface
+   */
+  protected $resourceManager;
+
+  /**
+   * The relationship items.
+   *
+   * @var array
+   */
+  protected $items;
+
+  /**
+   * Relationship constructor.
+   *
+   * @param \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager
+   *   The resource manager.
+   * @param string $field_name
+   *   The name of the relationship.
+   * @param int $cardinality
+   *   The relationship cardinality.
+   * @param \Drupal\jsonapi\EntityCollectionInterface $entities
+   *   A collection of entities.
+   * @param \Drupal\Core\Entity\EntityInterface $host_entity
+   *   The host entity.
+   * @param string $target_key
+   *   The property name of the relationship id.
+   */
+  public function __construct(ResourceManagerInterface $resource_manager, $field_name, $cardinality = FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, EntityCollectionInterface $entities, EntityInterface $host_entity, $target_key = 'target_id') {
+    $this->resourceManager = $resource_manager;
+    $this->propertyName = $field_name;
+    $this->cardinality = $cardinality;
+    $this->hostEntity = $host_entity;
+    $this->items = [];
+    foreach ($entities as $entity) {
+      $this->items[] = new RelationshipItem(
+        $resource_manager,
+        $entity,
+        $this,
+        $target_key
+      );
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCardinality() {
+    return $this->cardinality;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getHostEntity() {
+    return $this->hostEntity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setHostEntity(EntityInterface $hostEntity) {
+    $this->hostEntity = $hostEntity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    // Hard coded to TRUE. Revisit this if we need more control over this.
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropertyName() {
+    return $this->propertyName;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getItems() {
+    return $this->items;
+  }
+
+}
diff --git a/src/RelationshipInterface.php b/src/RelationshipInterface.php
new file mode 100644
index 0000000..8789b2c
--- /dev/null
+++ b/src/RelationshipInterface.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\jsonapi;
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Interface RelationshipInterface.
+ *
+ * @package Drupal\jsonapi
+ */
+interface RelationshipInterface {
+
+  /**
+   * Gets the cardinality.
+   *
+   * @return mixed
+   */
+  public function getCardinality();
+
+  /**
+   * Gets the hostEntity.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   */
+  public function getHostEntity();
+
+  /**
+   * Sets the hostEntity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $hostEntity
+   */
+  public function setHostEntity(EntityInterface $hostEntity);
+
+  /**
+   * Gets the field name.
+   *
+   * @return string
+   */
+  public function getPropertyName();
+
+  /**
+   * Gets the items.
+   *
+   * @return array
+   */
+  public function getItems();
+
+}
\ No newline at end of file
diff --git a/src/RelationshipItem.php b/src/RelationshipItem.php
new file mode 100644
index 0000000..bd97e93
--- /dev/null
+++ b/src/RelationshipItem.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Drupal\jsonapi;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\jsonapi\Configuration\ResourceManagerInterface;
+
+class RelationshipItem implements RelationshipItemInterface {
+
+  /**
+   * The target key name.
+   *
+   * @param string
+   */
+  protected $targetKey = 'target_id';
+
+  /**
+   * The target entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface
+   */
+  protected $targetEntity;
+
+  /**
+   * The target resource config.
+   *
+   * @param \Drupal\jsonapi\Configuration\ResourceConfigInterface
+   */
+  protected $targetResourceConfig;
+
+  /**
+   * The parent relationship.
+   *
+   * @var RelationshipInterface
+   */
+  protected $parent;
+
+  /**
+   * Relationship item constructor.
+   *
+   * @param \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager
+   *   The resource manager.
+   * @param \Drupal\Core\Entity\EntityInterface $target_entity
+   *   The entity this relationship points to.
+   * @param RelationshipInterface
+   *   The parent of this item.
+   * @param string $target_key
+   *   The key name of the target relationship.
+   */
+  public function __construct(ResourceManagerInterface $resource_manager, EntityInterface $target_entity, RelationshipInterface $parent, $target_key = 'target_id') {
+    $this->targetResourceConfig = $resource_manager->get(
+      $target_entity->getEntityTypeId(),
+      $target_entity->bundle()
+    );
+    $this->targetKey = $target_key;
+    $this->targetEntity = $target_entity;
+    $this->parent = $parent;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTargetEntity() {
+    return $this->targetEntity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTargetResourceConfig() {
+    return $this->targetResourceConfig;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue() {
+    $method = $this->getTargetResourceConfig()->getIdKey() == 'uuid' ?: 'id';
+    return [$this->targetKey => $this->getTargetEntity()->{$method}()];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getParent() {
+    return $this->parent;
+  }
+
+}
diff --git a/src/RelationshipItemInterface.php b/src/RelationshipItemInterface.php
new file mode 100644
index 0000000..e910a70
--- /dev/null
+++ b/src/RelationshipItemInterface.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\jsonapi;
+
+interface RelationshipItemInterface {
+
+  /**
+   * Gets the target entity.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   */
+  public function getTargetEntity();
+
+  /**
+   * Gets the targetResourceConfig.
+   *
+   * @return mixed
+   */
+  public function getTargetResourceConfig();
+
+  /**
+   * Gets the relationship value.
+   *
+   * Defaults to the entity ID.
+   *
+   * @return string
+   */
+  public function getValue();
+
+  /**
+   * Gets the relationship object that contains this relationship item.
+   *
+   * @return RelationshipInterface
+   */
+  public function getParent();
+
+}
\ No newline at end of file
diff --git a/src/Routing/Routes.php b/src/Routing/Routes.php
index a507841..a6af360 100644
--- a/src/Routing/Routes.php
+++ b/src/Routing/Routes.php
@@ -95,7 +95,7 @@ class Routes implements ContainerInjectionInterface {
         '_is_jsonapi' => TRUE,
       ];
 
-      // Collection endpoint, like /api/photos.
+      // Collection endpoint, like /api/file/photo.
       $route_collection = (new Route($partial_path))
         ->addDefaults($defaults)
         ->setRequirement('_entity_type', $entity_type)
@@ -110,7 +110,7 @@ class Routes implements ContainerInjectionInterface {
       $route_collection->addOptions($options);
       $collection->add($route_key . 'collection', $route_collection);
 
-      // Individual endpoint, like /api/photos/123.
+      // Individual endpoint, like /api/file/photo/123.
       $parameters = [$entity_type => ['type' => 'entity:' . $entity_type]];
       $route_individual = (new Route(sprintf('%s/{%s}', $partial_path, $entity_type)))
         ->addDefaults($defaults)
@@ -128,7 +128,7 @@ class Routes implements ContainerInjectionInterface {
       $route_individual->addOptions($options);
       $collection->add($route_key . 'individual', $route_individual);
 
-      // Related resource, like /api/photos/123/comments.
+      // Related resource, like /api/file/photo/123/comments.
       $route_related = (new Route(sprintf('%s/{%s}/{related}', $partial_path, $entity_type)))
         ->addDefaults($defaults)
         ->setRequirement('_entity_type', $entity_type)
@@ -144,7 +144,7 @@ class Routes implements ContainerInjectionInterface {
       $route_related->addOptions($options);
       $collection->add($route_key . 'related', $route_related);
 
-      // Related endpoint, like /api/photos/123/relationships/comments.
+      // Related endpoint, like /api/file/photo/123/relationships/comments.
       $route_relationship = (new Route(sprintf('%s/{%s}/relationships/{related}', $partial_path, $entity_type)))
         ->addDefaults($defaults + ['_on_relationship' => TRUE])
         ->setRequirement('_entity_type', $entity_type)
diff --git a/tests/src/Kernel/Normalizer/DocumentRootNormalizerTest.php b/tests/src/Kernel/Normalizer/DocumentRootNormalizerTest.php
index d992260..d20a5ee 100644
--- a/tests/src/Kernel/Normalizer/DocumentRootNormalizerTest.php
+++ b/tests/src/Kernel/Normalizer/DocumentRootNormalizerTest.php
@@ -122,15 +122,16 @@ class DocumentRootNormalizerTest extends KernelTestBase {
     $query->get('include')->willReturn('uid');
     $query->getIterator()->willReturn(new \ArrayIterator());
     $request->query = $query->reveal();
-    $route = $this->prophesize(Route::class);
-    $route->getPath()->willReturn('/node/article/{node}');
-    $route->getRequirement('_entity_type')->willReturn('node');
-    $route->getRequirement('_bundle')->willReturn('article');
-    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route->reveal());
+    $route = new Route('/node/article/{node}', [], [
+      '_entity_type' => 'node',
+      '_bundle' => 'article',
+    ]);
+    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route);
     $document_wrapper = $this->prophesize(DocumentWrapper::class);
     $document_wrapper->getData()->willReturn($this->node);
     $resource_config = $this->prophesize(ResourceConfigInterface::CLASS);
     $resource_config->getTypeName()->willReturn('node--article');
+    $resource_config->getBundleId()->willReturn('article');
     $resource_config->getIdKey()->willReturn('id');
     \Drupal::configFactory()->getEditable('jsonapi.resource_info')
       ->set('id_field', 'id')
@@ -138,7 +139,7 @@ class DocumentRootNormalizerTest extends KernelTestBase {
 
     // Make sure the route contains the entity type and bundle.
     $current_context = $this->container->get('jsonapi.current_context');
-    $current_context->setCurrentRoute($route->reveal());
+    $current_context->setCurrentRoute($route);
 
     $this->container->set('jsonapi.current_context', $current_context);
     $this->container->get('serializer');
@@ -238,65 +239,6 @@ class DocumentRootNormalizerTest extends KernelTestBase {
   /**
    * @covers ::normalize
    */
-  public function testNormalizeNoBundle() {
-    $request = $this->prophesize(Request::class);
-    $query = $this->prophesize(ParameterBag::class);
-    $query->get('fields')->willReturn([]);
-    $query->get('include')->willReturn(NULL);
-    $query->getIterator()->willReturn(new \ArrayIterator());
-    $request->query = $query->reveal();
-    $route = $this->prophesize(Route::class);
-    $route->getPath()->willReturn('/node/{node}');
-    $route->getRequirement('_entity_type')->willReturn('node');
-    $route->getRequirement('_bundle')->willReturn(NULL);
-    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route->reveal());
-    $document_wrapper = $this->prophesize(DocumentWrapper::class);
-    $document_wrapper->getData()->willReturn($this->node);
-    $resource_config = $this->prophesize(ResourceConfigInterface::CLASS);
-    $resource_config->getTypeName()->willReturn('node');
-    $resource_config->getIdKey()->willReturn('id');
-    $resource_config->getBundleId()->willReturn(NULL);
-
-    // Make sure the route contains the entity type.
-    /** @var \Drupal\jsonapi\Context\CurrentContextInterface $current_context */
-    $current_context = $this->container->get('jsonapi.current_context');
-    $current_context->setCurrentRoute($route->reveal());
-
-    $this->container->set('jsonapi.current_context', $current_context);
-    $this->container->get('serializer');
-    $normalized = $this
-      ->container
-      ->get('serializer.normalizer.document_root.jsonapi')
-      ->normalize(
-        $document_wrapper->reveal(),
-        'api_json',
-        [
-          'request' => $request->reveal(),
-          'resource_config' => $resource_config->reveal(),
-        ]
-      );
-    $this->assertSame($normalized['data']['attributes']['title'], 'dummy_title');
-    $this->assertEquals($normalized['data']['id'], 1);
-    $this->assertSame([
-      'data' => [
-        'type' => 'node_type--node_type',
-        'id' => 'article',
-      ],
-      'links' => [
-        'self' => 'dummy_entity_link',
-        'related' => 'dummy_entity_link',
-      ],
-    ], $normalized['data']['relationships']['type']);
-    $this->assertTrue(isset($normalized['data']['attributes']['created']));
-    // The body field and field_tags are attached to the bundle, so they should not be present here.
-    $this->assertTrue(!isset($normalized['data']['attributes']['body']));
-    $this->assertTrue(!isset($normalized['data']['attributes']['field_tags']));
-    $this->assertSame('node', $normalized['data']['type']);
-  }
-
-  /**
-   * @covers ::normalize
-   */
   public function testNormalizeConfig() {
     $request = $this->prophesize(Request::class);
     $query = $this->prophesize(ParameterBag::class);
@@ -306,20 +248,21 @@ class DocumentRootNormalizerTest extends KernelTestBase {
     $query->get('include')->willReturn(NULL);
     $query->getIterator()->willReturn(new \ArrayIterator());
     $request->query = $query->reveal();
-    $route = $this->prophesize(Route::class);
-    $route->getPath()->willReturn('/node_type/node_type/{node_type}');
-    $route->getRequirement('_entity_type')->willReturn('node');
-    $route->getRequirement('_bundle')->willReturn('article');
-    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route->reveal());
+    $route = new Route('/node_type/node_type/{node_type}', [], [
+      '_entity_type' => 'node_type',
+      '_bundle' => 'node_type',
+    ]);
+    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route);
     $document_wrapper = $this->prophesize(DocumentWrapper::class);
     $document_wrapper->getData()->willReturn($this->nodeType);
     $resource_config = $this->prophesize(ResourceConfigInterface::CLASS);
     $resource_config->getTypeName()->willReturn('node_type--node_type');
+    $resource_config->getBundleId()->willReturn('node_type');
     $resource_config->getIdKey()->willReturn('id');
 
     // Make sure the route contains the entity type and bundle.
     $current_context = $this->container->get('jsonapi.current_context');
-    $current_context->setCurrentRoute($route->reveal());
+    $current_context->setCurrentRoute($route);
 
     $this->container->set('jsonapi.current_context', $current_context);
     $this->container->get('serializer');
@@ -345,12 +288,11 @@ class DocumentRootNormalizerTest extends KernelTestBase {
   public function testDenormalize() {
     $payload = '{"type":"article", "data":{"attributes":{"title":"Testing article"}}}';
     $request = $this->prophesize(Request::class);
-    $route = $this->prophesize(Route::class);
-    $route->getPath()->willReturn('/node/article');
-    $route->getRequirement('_entity_type')->willReturn('node');
-    $route->getRequirement('_bundle')->willReturn('article');
-    $route->getDefault('_on_relationship')->willReturn(NULL);
-    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route->reveal());
+    $route = new Route('/node/article', ['_on_relationship' => NULL], [
+      '_entity_type' => 'node',
+      '_bundle' => 'article',
+    ]);
+    $request->get(RouteObjectInterface::ROUTE_OBJECT)->willReturn($route);
     $resource_config = $this->prophesize(ResourceConfigInterface::CLASS);
     $resource_config->getTypeName()->willReturn('node--article');
     $resource_config->getEntityTypeId()->willReturn('node');
diff --git a/tests/src/Unit/Normalizer/Value/ContentEntityNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/ContentEntityNormalizerValueTest.php
index bd54720..494f1c7 100644
--- a/tests/src/Unit/Normalizer/Value/ContentEntityNormalizerValueTest.php
+++ b/tests/src/Unit/Normalizer/Value/ContentEntityNormalizerValueTest.php
@@ -11,7 +11,7 @@ use Drupal\jsonapi\LinkManager\LinkManagerInterface;
 use Drupal\jsonapi\Normalizer\Value\ContentEntityNormalizerValue;
 use Drupal\jsonapi\Normalizer\Value\ContentEntityNormalizerValueInterface;
 use Drupal\jsonapi\Normalizer\Value\DocumentRootNormalizerValueInterface;
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceNormalizerValueInterface;
+use Drupal\jsonapi\Normalizer\Value\RelationshipNormalizerValueInterface;
 use Drupal\jsonapi\Normalizer\Value\FieldNormalizerValueInterface;
 use Drupal\Tests\UnitTestCase;
 use Prophecy\Argument;
@@ -43,7 +43,7 @@ class ContentEntityNormalizerValueTest extends UnitTestCase {
     $field1->getIncludes()->willReturn([]);
     $field1->getPropertyType()->willReturn('attributes');
     $field1->rasterizeValue()->willReturn('dummy_title');
-    $field2 = $this->prophesize(EntityReferenceNormalizerValueInterface::class);
+    $field2 = $this->prophesize(RelationshipNormalizerValueInterface::class);
     $field2->getPropertyType()->willReturn('relationships');
     $field2->rasterizeValue()->willReturn(['data' => ['type' => 'node', 'id' => 2]]);
     $included[] = $this->prophesize(DocumentRootNormalizerValueInterface::class);
diff --git a/tests/src/Unit/Normalizer/Value/DocumentRootNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/DocumentRootNormalizerValueTest.php
index 687f0a4..bb29ae7 100644
--- a/tests/src/Unit/Normalizer/Value/DocumentRootNormalizerValueTest.php
+++ b/tests/src/Unit/Normalizer/Value/DocumentRootNormalizerValueTest.php
@@ -8,7 +8,7 @@ use Drupal\jsonapi\Configuration\ResourceConfigInterface;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
 use Drupal\jsonapi\Normalizer\Value\DocumentRootNormalizerValue;
 use Drupal\jsonapi\Normalizer\Value\DocumentRootNormalizerValueInterface;
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceNormalizerValueInterface;
+use Drupal\jsonapi\Normalizer\Value\RelationshipNormalizerValueInterface;
 use Drupal\jsonapi\Normalizer\Value\FieldNormalizerValueInterface;
 use Drupal\Tests\UnitTestCase;
 use Prophecy\Argument;
@@ -40,7 +40,7 @@ class DocumentRootNormalizerValueTest extends UnitTestCase{
     $field1->getIncludes()->willReturn([]);
     $field1->getPropertyType()->willReturn('attributes');
     $field1->rasterizeValue()->willReturn('dummy_title');
-    $field2 = $this->prophesize(EntityReferenceNormalizerValueInterface::class);
+    $field2 = $this->prophesize(RelationshipNormalizerValueInterface::class);
     $field2->getPropertyType()->willReturn('relationships');
     $field2->rasterizeValue()->willReturn(['data' => ['type' => 'node', 'id' => 2]]);
     $included[] = $this->prophesize(DocumentRootNormalizerValue::class);
diff --git a/tests/src/Unit/Normalizer/Value/EntityReferenceItemNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php
similarity index 57%
rename from tests/src/Unit/Normalizer/Value/EntityReferenceItemNormalizerValueTest.php
rename to tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php
index 843adcd..5cb808c 100644
--- a/tests/src/Unit/Normalizer/Value/EntityReferenceItemNormalizerValueTest.php
+++ b/tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php
@@ -2,7 +2,8 @@
 
 namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value;
 
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceItemNormalizerValue;
+use Drupal\jsonapi\Configuration\ResourceConfigInterface;
+use Drupal\jsonapi\Normalizer\Value\RelationshipItemNormalizerValue;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -10,17 +11,19 @@ use Drupal\Tests\UnitTestCase;
  *
  * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
  *
- * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\EntityReferenceItemNormalizerValue
+ * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\RelationshipItemNormalizerValue
  * @group jsonapi
  */
-class EntityReferenceItemNormalizerValueTest extends UnitTestCase {
+class RelationshipItemNormalizerValueTest extends UnitTestCase {
 
   /**
    * @covers ::rasterizeValue
    * @dataProvider rasterizeValueProvider
    */
-  public function testRasterizeValue($values, $resource, $expected) {
-    $object = new EntityReferenceItemNormalizerValue($values, $resource);
+  public function testRasterizeValue($values, $resource_type, $expected) {
+    $resource = $this->prophesize(ResourceConfigInterface::class);
+    $resource->getTypeName()->willReturn($resource_type);
+    $object = new RelationshipItemNormalizerValue($values, $resource->reveal());
     $this->assertEquals($expected, $object->rasterizeValue());
   }
 
diff --git a/tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php
similarity index 82%
rename from tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php
rename to tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php
index 2a9b163..506b5b6 100644
--- a/tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php
+++ b/tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php
@@ -4,8 +4,8 @@ namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value;
 
 use Drupal\jsonapi\Configuration\ResourceConfigInterface;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceItemNormalizerValue;
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceNormalizerValue;
+use Drupal\jsonapi\Normalizer\Value\RelationshipItemNormalizerValue;
+use Drupal\jsonapi\Normalizer\Value\RelationshipNormalizerValue;
 use Drupal\jsonapi\Normalizer\Value\FieldItemNormalizerValue;
 use Drupal\Tests\UnitTestCase;
 use Prophecy\Argument;
@@ -15,10 +15,10 @@ use Prophecy\Argument;
  *
  * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
  *
- * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\EntityReferenceNormalizerValue
+ * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\RelationshipNormalizerValue
  * @group jsonapi
  */
-class EntityReferenceNormalizerValueTest extends UnitTestCase {
+class RelationshipNormalizerValueTest extends UnitTestCase {
 
   /**
    * @covers ::rasterizeValue
@@ -29,7 +29,7 @@ class EntityReferenceNormalizerValueTest extends UnitTestCase {
     $link_manager
       ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
       ->willReturn('dummy_entity_link');
-    $object = new EntityReferenceNormalizerValue($values, $cardinality, [
+    $object = new RelationshipNormalizerValue($values, $cardinality, [
       'link_manager' => $link_manager->reveal(),
       'host_entity_id' => 'lorem',
       'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
@@ -43,10 +43,10 @@ class EntityReferenceNormalizerValueTest extends UnitTestCase {
    */
   public function rasterizeValueProvider() {
     $uid_raw = 1;
-    $uid1 = $this->prophesize(EntityReferenceItemNormalizerValue::class);
+    $uid1 = $this->prophesize(RelationshipItemNormalizerValue::class);
     $uid1->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw++]);
     $uid1->getInclude()->willReturn(NULL);
-    $uid2 = $this->prophesize(EntityReferenceItemNormalizerValue::class);
+    $uid2 = $this->prophesize(RelationshipItemNormalizerValue::class);
     $uid2->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw]);
     $uid2->getInclude()->willReturn(NULL);
     $links = [
@@ -83,7 +83,7 @@ class EntityReferenceNormalizerValueTest extends UnitTestCase {
     $link_manager
       ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
       ->willReturn('dummy_entity_link');
-    $object = new EntityReferenceNormalizerValue([$uid1->reveal()], 1, [
+    $object = new RelationshipNormalizerValue([$uid1->reveal()], 1, [
       'link_manager' => $link_manager->reveal(),
       'host_entity_id' => 'lorem',
       'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
