diff --git a/jsonapi.services.yml b/jsonapi.services.yml
index 4fac6f0..1090dd1 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..f231379 100644
--- a/src/Normalizer/ConfigEntityNormalizer.php
+++ b/src/Normalizer/ConfigEntityNormalizer.php
@@ -3,6 +3,9 @@
 namespace Drupal\jsonapi\Normalizer;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\jsonapi\EntityCollection;
+use Drupal\jsonapi\Relationship;
+use Drupal\jsonapi\RelationshipInterface;
 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 
 /**
@@ -22,35 +25,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..745cd2b 100644
--- a/src/Normalizer/ContentEntityNormalizer.php
+++ b/src/Normalizer/ContentEntityNormalizer.php
@@ -2,12 +2,17 @@
 
 namespace Drupal\jsonapi\Normalizer;
 
+use Drupal\Core\Access\AccessibleInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Field\EntityReferenceFieldItemList;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\jsonapi\Configuration\ResourceConfigInterface;
 use Drupal\jsonapi\Context\CurrentContextInterface;
+use Drupal\jsonapi\EntityCollection;
 use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+use Drupal\jsonapi\Relationship;
+use Drupal\jsonapi\RelationshipInterface;
 use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
 
@@ -71,15 +76,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 +112,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 +145,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 +155,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 +180,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/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..1efd612 100644
--- a/src/Normalizer/DocumentRootNormalizerInterface.php
+++ b/src/Normalizer/DocumentRootNormalizerInterface.php
@@ -2,10 +2,20 @@
 
 
 namespace Drupal\jsonapi\Normalizer;
+use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
+use Drupal\jsonapi\EntityCollectionInterface;
 
 /**
  * Class DocumentRootNormalizerInterface.
  *
  * @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/EntityReferenceFieldNormalizer.php b/src/Normalizer/EntityReferenceFieldNormalizer.php
index c318fa6..0300d8d 100644
--- a/src/Normalizer/EntityReferenceFieldNormalizer.php
+++ b/src/Normalizer/EntityReferenceFieldNormalizer.php
@@ -6,9 +6,12 @@ use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
+use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 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 +68,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/EntityReferenceItemNormalizer.php b/src/Normalizer/EntityReferenceItemNormalizer.php
deleted file mode 100644
index 8c5daea..0000000
--- a/src/Normalizer/EntityReferenceItemNormalizer.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\Normalizer;
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
-use Drupal\jsonapi\Configuration\ResourceManagerInterface;
-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;
-
-  /**
-   * The interface or class that this Normalizer supports.
-   *
-   * @var string
-   */
-  protected $supportedInterfaceOrClass = EntityReferenceItem::class;
-
-  /**
-   * The manager for resource configuration.
-   *
-   * @var \Drupal\jsonapi\Configuration\ResourceManagerInterface
-   */
-  protected $resourceManager;
-
-  /**
-   * Instantiates a EntityReferenceItemNormalizer object.
-   *
-   * @param \Drupal\jsonapi\Configuration\ResourceManagerInterface $resource_manager
-   *   The resource manager.
-   */
-  public function __construct(ResourceManagerInterface $resource_manager) {
-    $this->resourceManager = $resource_manager;
-  }
-
-  /**
-   * {@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]];
-    }
-    if (isset($context['langcode'])) {
-      $values['lang'] = $context['langcode'];
-    }
-    $normalizer_value = new Value\EntityReferenceItemNormalizerValue(
-      $values,
-      $resource_config
-        ->getTypeName()
-    );
-
-    // 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));
-    }
-    return $normalizer_value;
-  }
-
-  /**
-   * 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.
-   */
-  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;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getUuid($data) {
-    if (isset($data['uuid'])) {
-      return NULL;
-    }
-    $uuid = $data['uuid'];
-    // The value may be a nested array like $uuid[0]['value'].
-    if (is_array($uuid) && isset($uuid[0]['value'])) {
-      $uuid = $uuid[0]['value'];
-    }
-    return $uuid;
-  }
-
-}
diff --git a/src/Normalizer/FieldItemNormalizer.php b/src/Normalizer/FieldItemNormalizer.php
index 0a504a4..d4ac599 100644
--- a/src/Normalizer/FieldItemNormalizer.php
+++ b/src/Normalizer/FieldItemNormalizer.php
@@ -27,8 +27,8 @@ class FieldItemNormalizer extends NormalizerBase {
   /**
    * {@inheritdoc}
    */
-  public function normalize($field_item, $format = NULL, array $context = array()) {
-    $values = $field_item->toArray();
+  public function normalize($relationship_item, $format = NULL, array $context = array()) {
+    $values = $relationship_item->toArray();
     if (isset($context['langcode'])) {
       $values['lang'] = $context['langcode'];
     }
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/RelationshipItemNormalizer.php b/src/Normalizer/RelationshipItemNormalizer.php
new file mode 100644
index 0000000..1127699
--- /dev/null
+++ b/src/Normalizer/RelationshipItemNormalizer.php
@@ -0,0 +1,125 @@
+<?php
+
+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\Relationship;
+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 RelationshipItemNormalizer extends FieldItemNormalizer implements UuidReferenceInterface {
+
+  /**
+   * The interface or class that this Normalizer supports.
+   *
+   * @var string
+   */
+  protected $supportedInterfaceOrClass = RelationshipItemInterface::class;
+
+  /**
+   * The manager for resource configuration.
+   *
+   * @var \Drupal\jsonapi\Configuration\ResourceManagerInterface
+   */
+  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, DocumentRootNormalizerInterface $document_root_normalizer) {
+    $this->resourceManager = $resource_manager;
+    $this->documentRootNormalizer = $document_root_normalizer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  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\RelationshipItemNormalizerValue(
+      $values,
+      $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($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;
+  }
+
+  /**
+   * 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.
+   */
+  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;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getUuid($data) {
+    if (isset($data['uuid'])) {
+      return NULL;
+    }
+    $uuid = $data['uuid'];
+    // The value may be a nested array like $uuid[0]['value'].
+    if (is_array($uuid) && isset($uuid[0]['value'])) {
+      $uuid = $uuid[0]['value'];
+    }
+    return $uuid;
+  }
+
+}
diff --git a/src/Normalizer/RelationshipNormalizer.php b/src/Normalizer/RelationshipNormalizer.php
new file mode 100644
index 0000000..c09ae4f
--- /dev/null
+++ b/src/Normalizer/RelationshipNormalizer.php
@@ -0,0 +1,134 @@
+<?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 Drupal\jsonapi\RelationshipInterface;
+use League\Container\ContainerAwareTrait;
+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/EntityReferenceItemNormalizerValue.php b/src/Normalizer/Value/EntityReferenceItemNormalizerValue.php
deleted file mode 100644
index 45e06a6..0000000
--- a/src/Normalizer/Value/EntityReferenceItemNormalizerValue.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\Normalizer\Value;
-
-/**
- * Class FieldItemNormalizerValue.
- *
- * @package Drupal\jsonapi\Normalizer\Value
- */
-class EntityReferenceItemNormalizerValue extends FieldItemNormalizerValue implements EntityReferenceItemNormalizerValueInterface {
-
-  /**
-   * Resource path.
-   *
-   * @param string
-   */
-  protected $resource;
-
-  /**
-   * Instantiates a EntityReferenceItemNormalizerValue object.
-   *
-   * @param array $values
-   *   The values.
-   * @param string $resource
-   *   The resource path of the target entity.
-   */
-  public function __construct(array $values, $resource) {
-    parent::__construct($values);
-    $this->resource = $resource;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function rasterizeValue() {
-    if (!$value = parent::rasterizeValue()) {
-      return $value;
-    }
-    return [
-      'type' => $this->resource,
-      'id' => $value,
-    ];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setResource($resource) {
-    $this->resource = $resource;
-  }
-
-}
diff --git a/src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php b/src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php
deleted file mode 100644
index 1961c83..0000000
--- a/src/Normalizer/Value/EntityReferenceItemNormalizerValueInterface.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\Normalizer\Value;
-
-/**
- * Class EntityReferenceItemNormalizerValueInterface.
- *
- * @package Drupal\jsonapi\Normalizer\Value
- */
-interface EntityReferenceItemNormalizerValueInterface extends FieldItemNormalizerValueInterface {
-
-  /**
-   * Sets the resource.
-   *
-   * @param string $resource
-   *   The resource to set.
-   */
-  public function setResource($resource);
-
-}
diff --git a/src/Normalizer/Value/EntityReferenceNormalizerValue.php b/src/Normalizer/Value/EntityReferenceNormalizerValue.php
deleted file mode 100644
index 0cc43f1..0000000
--- a/src/Normalizer/Value/EntityReferenceNormalizerValue.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\Normalizer\Value;
-
-/**
- * Class EntityReferenceListNormalizerValue.
- *
- * @package Drupal\jsonapi\Normalizer\Value
- */
-class EntityReferenceNormalizerValue extends FieldNormalizerValue implements EntityReferenceNormalizerValueInterface {
-
-  /**
-   * The link manager.
-   *
-   * @param \Drupal\jsonapi\LinkManager\LinkManagerInterface
-   */
-  protected $linkManager;
-
-  /**
-   * The resource config for the link generation.
-   *
-   * @var \Drupal\jsonapi\Configuration\ResourceConfigInterface
-   */
-  protected $resourceConfig;
-
-  /**
-   * The field name for the link generation.
-   *
-   * @var string
-   */
-  protected $fieldName;
-
-  /**
-   * The entity ID for the host entity.
-   *
-   * @var string
-   */
-  protected $hostEntityId;
-
-  /**
-   * Instantiate a EntityReferenceNormalizerValue object.
-   *
-   * @param EntityReferenceItemNormalizerValue[] $values
-   *   The normalized result.
-   * @param int $cardinality
-   *   The number of fields for the field list.
-   * @param array $link_context
-   *   All the objects and variables needed to generate the links for this
-   *   relationship.
-   */
-  public function __construct(array $values, $cardinality, array $link_context) {
-    $this->hostEntityId = $link_context['host_entity_id'];
-    $this->fieldName = $link_context['field_name'];
-    $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) {
-        throw new \RuntimeException(sprintf('Unexpected normalizer item value for this %s.', get_called_class()));
-      }
-    });
-    parent::__construct($values, $cardinality);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function rasterizeValue() {
-    if (!$value = parent::rasterizeValue()) {
-      // According to the JSON API specs empty relationships are either NULL or
-      // an empty array.
-      return $this->cardinality == 1 ? ['data' => NULL] : ['data' => []];
-    }
-    // Generate the links for the relationship.
-    $route_parameters = ['related' => $this->fieldName];
-    return [
-      'data' => $value,
-      'links' => [
-        'self' => $this->linkManager->getEntityLink(
-          $this->hostEntityId,
-          $this->resourceConfig,
-          $route_parameters,
-          'relationship'
-        ),
-        'related' => $this->linkManager->getEntityLink(
-          $this->hostEntityId,
-          $this->resourceConfig,
-          $route_parameters,
-          'related'
-        ),
-      ],
-    ];
-  }
-
-}
diff --git a/src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php b/src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php
deleted file mode 100644
index cb68951..0000000
--- a/src/Normalizer/Value/EntityReferenceNormalizerValueInterface.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\Normalizer\Value;
-
-/**
- * Class EntityReferenceListNormalizerValueInterface.
- *
- * @package Drupal\jsonapi\Normalizer\Value
- */
-interface EntityReferenceNormalizerValueInterface extends FieldNormalizerValueInterface {}
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/RelationshipItemNormalizerValue.php b/src/Normalizer/Value/RelationshipItemNormalizerValue.php
new file mode 100644
index 0000000..a437ff7
--- /dev/null
+++ b/src/Normalizer/Value/RelationshipItemNormalizerValue.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace Drupal\jsonapi\Normalizer\Value;
+
+/**
+ * Class FieldItemNormalizerValue.
+ *
+ * @package Drupal\jsonapi\Normalizer\Value
+ */
+class RelationshipItemNormalizerValue extends FieldItemNormalizerValue implements RelationshipItemNormalizerValueInterface {
+
+  /**
+   * Resource path.
+   *
+   * @param string
+   */
+  protected $resource;
+
+  /**
+   * Instantiates a EntityReferenceItemNormalizerValue object.
+   *
+   * @param array $values
+   *   The values.
+   * @param string $resource
+   *   The resource type of the target entity.
+   */
+  public function __construct(array $values, $resource) {
+    parent::__construct($values);
+    $this->resource = $resource;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rasterizeValue() {
+    if (!$value = parent::rasterizeValue()) {
+      return $value;
+    }
+    return [
+      'type' => $this->resource->getTypeName(),
+      'id' => $value,
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setResource($resource) {
+    $this->resource = $resource;
+  }
+
+}
diff --git a/src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php b/src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php
new file mode 100644
index 0000000..1655e66
--- /dev/null
+++ b/src/Normalizer/Value/RelationshipItemNormalizerValueInterface.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Drupal\jsonapi\Normalizer\Value;
+
+/**
+ * Class EntityReferenceItemNormalizerValueInterface.
+ *
+ * @package Drupal\jsonapi\Normalizer\Value
+ */
+interface RelationshipItemNormalizerValueInterface extends FieldItemNormalizerValueInterface {
+
+  /**
+   * Sets the resource.
+   *
+   * @param string $resource
+   *   The resource to set.
+   */
+  public function setResource($resource);
+
+}
diff --git a/src/Normalizer/Value/RelationshipNormalizerValue.php b/src/Normalizer/Value/RelationshipNormalizerValue.php
new file mode 100644
index 0000000..88e8ffa
--- /dev/null
+++ b/src/Normalizer/Value/RelationshipNormalizerValue.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Drupal\jsonapi\Normalizer\Value;
+
+/**
+ * Class EntityReferenceListNormalizerValue.
+ *
+ * @package Drupal\jsonapi\Normalizer\Value
+ */
+class RelationshipNormalizerValue extends FieldNormalizerValue implements RelationshipNormalizerValueInterface {
+
+  /**
+   * The link manager.
+   *
+   * @param \Drupal\jsonapi\LinkManager\LinkManagerInterface
+   */
+  protected $linkManager;
+
+  /**
+   * The resource config for the link generation.
+   *
+   * @var \Drupal\jsonapi\Configuration\ResourceConfigInterface
+   */
+  protected $resourceConfig;
+
+  /**
+   * The field name for the link generation.
+   *
+   * @var string
+   */
+  protected $fieldName;
+
+  /**
+   * The entity ID for the host entity.
+   *
+   * @var string
+   */
+  protected $hostEntityId;
+
+  /**
+   * Instantiate a EntityReferenceNormalizerValue object.
+   *
+   * @param RelationshipItemNormalizerValue[] $values
+   *   The normalized result.
+   * @param int $cardinality
+   *   The number of fields for the field list.
+   * @param array $link_context
+   *   All the objects and variables needed to generate the links for this
+   *   relationship.
+   */
+  public function __construct(array $values, $cardinality, array $link_context) {
+    $this->hostEntityId = $link_context['host_entity_id'];
+    $this->fieldName = $link_context['field_name'];
+    $this->linkManager = $link_context['link_manager'];
+    $this->resourceConfig = $link_context['resource_config'];
+    array_walk($values, function ($field_item_value) {
+      if (!$field_item_value instanceof RelationshipItemNormalizerValueInterface) {
+        throw new \RuntimeException(sprintf('Unexpected normalizer item value for this %s.', get_called_class()));
+      }
+    });
+    parent::__construct($values, $cardinality);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function rasterizeValue() {
+    if (!$value = parent::rasterizeValue()) {
+      // According to the JSON API specs empty relationships are either NULL or
+      // an empty array.
+      return $this->cardinality == 1 ? ['data' => NULL] : ['data' => []];
+    }
+    // Generate the links for the relationship.
+    $route_parameters = ['related' => $this->fieldName];
+    return [
+      'data' => $value,
+      'links' => [
+        'self' => $this->linkManager->getEntityLink(
+          $this->hostEntityId,
+          $this->resourceConfig,
+          $route_parameters,
+          'relationship'
+        ),
+        'related' => $this->linkManager->getEntityLink(
+          $this->hostEntityId,
+          $this->resourceConfig,
+          $route_parameters,
+          'related'
+        ),
+      ],
+    ];
+  }
+
+}
diff --git a/src/Normalizer/Value/RelationshipNormalizerValueInterface.php b/src/Normalizer/Value/RelationshipNormalizerValueInterface.php
new file mode 100644
index 0000000..da0908a
--- /dev/null
+++ b/src/Normalizer/Value/RelationshipNormalizerValueInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Drupal\jsonapi\Normalizer\Value;
+
+/**
+ * Class EntityReferenceListNormalizerValueInterface.
+ *
+ * @package Drupal\jsonapi\Normalizer\Value
+ */
+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..0d431e4
--- /dev/null
+++ b/src/RelationshipItem.php
@@ -0,0 +1,91 @@
+<?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' ?
+      '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/EntityReferenceItemNormalizerValueTest.php
deleted file mode 100644
index 843adcd..0000000
--- a/tests/src/Unit/Normalizer/Value/EntityReferenceItemNormalizerValueTest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value;
-
-use Drupal\jsonapi\Normalizer\Value\EntityReferenceItemNormalizerValue;
-use Drupal\Tests\UnitTestCase;
-
-/**
- * Class EntityReferenceItemNormalizerValueTest.
- *
- * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
- *
- * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\EntityReferenceItemNormalizerValue
- * @group jsonapi
- */
-class EntityReferenceItemNormalizerValueTest extends UnitTestCase {
-
-  /**
-   * @covers ::rasterizeValue
-   * @dataProvider rasterizeValueProvider
-   */
-  public function testRasterizeValue($values, $resource, $expected) {
-    $object = new EntityReferenceItemNormalizerValue($values, $resource);
-    $this->assertEquals($expected, $object->rasterizeValue());
-  }
-
-  /**
-   * Data provider for testRasterizeValue.
-   */
-  public function rasterizeValueProvider() {
-    return [
-      [['target_id' => 1], 'node', ['type' => 'node', 'id' => 1]],
-      [['value' => 1], 'node', ['type' => 'node', 'id' => 1]],
-      [[1], 'node', ['type' => 'node', 'id' => 1]],
-      [[], 'node', []],
-      [[NULL], 'node', NULL],
-    ];
-  }
-}
diff --git a/tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php
deleted file mode 100644
index 2a9b163..0000000
--- a/tests/src/Unit/Normalizer/Value/EntityReferenceNormalizerValueTest.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-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\FieldItemNormalizerValue;
-use Drupal\Tests\UnitTestCase;
-use Prophecy\Argument;
-
-/**
- * Class EntityReferenceNormalizerValueTes.
- *
- * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
- *
- * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\EntityReferenceNormalizerValue
- * @group jsonapi
- */
-class EntityReferenceNormalizerValueTest extends UnitTestCase {
-
-  /**
-   * @covers ::rasterizeValue
-   * @dataProvider rasterizeValueProvider
-   */
-  public function testRasterizeValue($values, $cardinality, $expected) {
-    $link_manager = $this->prophesize(LinkManagerInterface::class);
-    $link_manager
-      ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
-      ->willReturn('dummy_entity_link');
-    $object = new EntityReferenceNormalizerValue($values, $cardinality, [
-      'link_manager' => $link_manager->reveal(),
-      'host_entity_id' => 'lorem',
-      'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
-      'field_name' => 'ipsum',
-    ]);
-    $this->assertEquals($expected, $object->rasterizeValue());
-  }
-
-  /**
-   * Data provider fortestRasterizeValue.
-   */
-  public function rasterizeValueProvider() {
-    $uid_raw = 1;
-    $uid1 = $this->prophesize(EntityReferenceItemNormalizerValue::class);
-    $uid1->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw++]);
-    $uid1->getInclude()->willReturn(NULL);
-    $uid2 = $this->prophesize(EntityReferenceItemNormalizerValue::class);
-    $uid2->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw]);
-    $uid2->getInclude()->willReturn(NULL);
-    $links = [
-      'self' => 'dummy_entity_link',
-      'related' => 'dummy_entity_link',
-    ];
-    return [
-      [[$uid1->reveal()], 1, [
-        'data' => ['type' => 'user', 'id' => 1],
-        'links' => $links,
-      ]],
-      [
-        [$uid1->reveal(), $uid2->reveal()], 2, [
-          'data' => [
-            ['type' => 'user', 'id' => 1],
-            ['type' => 'user', 'id' => 2],
-          ],
-          'links' => $links,
-        ],
-      ],
-    ];
-  }
-
-  /**
-   * @covers ::rasterizeValue
-   *
-   * @expectedException \RuntimeException
-   */
-  public function testRasterizeValueFails() {
-    $uid1 = $this->prophesize(FieldItemNormalizerValue::class);
-    $uid1->rasterizeValue()->willReturn(1);
-    $uid1->getInclude()->willReturn(NULL);
-    $link_manager = $this->prophesize(LinkManagerInterface::class);
-    $link_manager
-      ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
-      ->willReturn('dummy_entity_link');
-    $object = new EntityReferenceNormalizerValue([$uid1->reveal()], 1, [
-      'link_manager' => $link_manager->reveal(),
-      'host_entity_id' => 'lorem',
-      'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
-      'field_name' => 'ipsum',
-    ]);
-    $object->rasterizeValue();
-    // If the exception was not thrown, then the following fails.
-    $this->assertTrue(FALSE);
-  }
-
-}
diff --git a/tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php
new file mode 100644
index 0000000..5cb808c
--- /dev/null
+++ b/tests/src/Unit/Normalizer/Value/RelationshipItemNormalizerValueTest.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value;
+
+use Drupal\jsonapi\Configuration\ResourceConfigInterface;
+use Drupal\jsonapi\Normalizer\Value\RelationshipItemNormalizerValue;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Class EntityReferenceItemNormalizerValueTest.
+ *
+ * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
+ *
+ * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\RelationshipItemNormalizerValue
+ * @group jsonapi
+ */
+class RelationshipItemNormalizerValueTest extends UnitTestCase {
+
+  /**
+   * @covers ::rasterizeValue
+   * @dataProvider rasterizeValueProvider
+   */
+  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());
+  }
+
+  /**
+   * Data provider for testRasterizeValue.
+   */
+  public function rasterizeValueProvider() {
+    return [
+      [['target_id' => 1], 'node', ['type' => 'node', 'id' => 1]],
+      [['value' => 1], 'node', ['type' => 'node', 'id' => 1]],
+      [[1], 'node', ['type' => 'node', 'id' => 1]],
+      [[], 'node', []],
+      [[NULL], 'node', NULL],
+    ];
+  }
+}
diff --git a/tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php
new file mode 100644
index 0000000..506b5b6
--- /dev/null
+++ b/tests/src/Unit/Normalizer/Value/RelationshipNormalizerValueTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value;
+
+use Drupal\jsonapi\Configuration\ResourceConfigInterface;
+use Drupal\jsonapi\LinkManager\LinkManagerInterface;
+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;
+
+/**
+ * Class EntityReferenceNormalizerValueTes.
+ *
+ * @package Drupal\Tests\jsonapi\Unit\Normalizer\Value
+ *
+ * @coversDefaultClass \Drupal\jsonapi\Normalizer\Value\RelationshipNormalizerValue
+ * @group jsonapi
+ */
+class RelationshipNormalizerValueTest extends UnitTestCase {
+
+  /**
+   * @covers ::rasterizeValue
+   * @dataProvider rasterizeValueProvider
+   */
+  public function testRasterizeValue($values, $cardinality, $expected) {
+    $link_manager = $this->prophesize(LinkManagerInterface::class);
+    $link_manager
+      ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
+      ->willReturn('dummy_entity_link');
+    $object = new RelationshipNormalizerValue($values, $cardinality, [
+      'link_manager' => $link_manager->reveal(),
+      'host_entity_id' => 'lorem',
+      'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
+      'field_name' => 'ipsum',
+    ]);
+    $this->assertEquals($expected, $object->rasterizeValue());
+  }
+
+  /**
+   * Data provider fortestRasterizeValue.
+   */
+  public function rasterizeValueProvider() {
+    $uid_raw = 1;
+    $uid1 = $this->prophesize(RelationshipItemNormalizerValue::class);
+    $uid1->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw++]);
+    $uid1->getInclude()->willReturn(NULL);
+    $uid2 = $this->prophesize(RelationshipItemNormalizerValue::class);
+    $uid2->rasterizeValue()->willReturn(['type' => 'user', 'id' => $uid_raw]);
+    $uid2->getInclude()->willReturn(NULL);
+    $links = [
+      'self' => 'dummy_entity_link',
+      'related' => 'dummy_entity_link',
+    ];
+    return [
+      [[$uid1->reveal()], 1, [
+        'data' => ['type' => 'user', 'id' => 1],
+        'links' => $links,
+      ]],
+      [
+        [$uid1->reveal(), $uid2->reveal()], 2, [
+          'data' => [
+            ['type' => 'user', 'id' => 1],
+            ['type' => 'user', 'id' => 2],
+          ],
+          'links' => $links,
+        ],
+      ],
+    ];
+  }
+
+  /**
+   * @covers ::rasterizeValue
+   *
+   * @expectedException \RuntimeException
+   */
+  public function testRasterizeValueFails() {
+    $uid1 = $this->prophesize(FieldItemNormalizerValue::class);
+    $uid1->rasterizeValue()->willReturn(1);
+    $uid1->getInclude()->willReturn(NULL);
+    $link_manager = $this->prophesize(LinkManagerInterface::class);
+    $link_manager
+      ->getEntityLink(Argument::any(), Argument::any(), Argument::type('array'), Argument::type('string'))
+      ->willReturn('dummy_entity_link');
+    $object = new RelationshipNormalizerValue([$uid1->reveal()], 1, [
+      'link_manager' => $link_manager->reveal(),
+      'host_entity_id' => 'lorem',
+      'resource_config' => $this->prophesize(ResourceConfigInterface::class)->reveal(),
+      'field_name' => 'ipsum',
+    ]);
+    $object->rasterizeValue();
+    // If the exception was not thrown, then the following fails.
+    $this->assertTrue(FALSE);
+  }
+
+}
