diff --git a/metatag.services.yml b/metatag.services.yml
index ec8a204..2de8ce6 100644
--- a/metatag.services.yml
+++ b/metatag.services.yml
@@ -38,3 +38,10 @@ services:
     arguments: ['@?console.extension_manager', '@?console.renderer']
     tags:
       - { name: drupal.generator }
+
+  # Priority of the metatag normalizer must be higher than other general-purpose typed data and field item normalizers.
+  metatag.normalizer.metatag_field_item:
+    class: Drupal\metatag\Normalizer\FieldItemNormalizer
+    arguments: ['@metatag.token']
+    tags:
+      - { name: normalizer, priority: 30 }
diff --git a/src/MetatagToken.php b/src/MetatagToken.php
index 10921ff..1e2b25e 100644
--- a/src/MetatagToken.php
+++ b/src/MetatagToken.php
@@ -34,8 +34,11 @@ class MetatagToken {
    *
    * @return mixed|string $string
    */
-  public function replace($string, $data, $options = []) {
-    $options['clear'] = TRUE;
+  public function replace($string, array $data = [], $options = []) {
+    // Set default requirements for metatag unless options specify otherwise.
+    $options = $options + [
+      'clear' => TRUE
+    ];
 
     $replaced = $this->token->replace($string, $data, $options);
 
diff --git a/src/Normalizer/FieldItemNormalizer.php b/src/Normalizer/FieldItemNormalizer.php
new file mode 100644
index 0000000..5ae407b
--- /dev/null
+++ b/src/Normalizer/FieldItemNormalizer.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Drupal\metatag\Normalizer;
+
+use Drupal\metatag\MetatagToken;
+use Drupal\Core\Field\FieldItemInterface;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Drupal\serialization\Normalizer\NormalizerBase;
+
+/**
+ * Converts the Metatag field item object structure to METATAG array structure.
+ */
+class FieldItemNormalizer extends NormalizerBase {
+
+  /**
+   * Metatag Token service.
+   *
+   * @var \Drupal\metatag\MetatagToken
+   */
+  protected $metatagToken;
+
+  /**
+   * Construct a FieldItemNormalizer.
+   *
+   * @param \Drupal\metatag\MetatagToken $metatag_token
+   *   The metatag token service.
+   */
+  public function __construct(MetatagToken $metatag_token) {
+    $this->metatagToken = $metatag_token;
+  }
+
+  /**
+   * The interface or class that this Normalizer supports.
+   *
+   * @var string
+   */
+  protected $supportedInterfaceOrClass = 'Drupal\metatag\Plugin\Field\FieldType\MetatagFieldItem';
+
+  /**
+   * {@inheritdoc}}
+   */
+  public function normalize($field_item, $format = NULL, array $context = []) {
+    $normalized = $this->getFieldValues($field_item);
+
+    if (isset($context['langcode'])) {
+      $normalized['lang'] = $context['langcode'];
+    }
+
+    // Convert tokens if there are any.
+    //
+    // Tokens are not cleared on failure to replace in case the token is useful.
+    //
+    // @todo Move token processed version of content to a 'processed' key.
+    $entity = $field_item->getEntity();
+    $normalized['value'] = array_map(function($tag) use ($entity) {
+      return $this->metatagToken->replace(
+        $tag,
+        [
+          $entity->getEntityTypeId() => $entity,
+        ],
+        [
+          'clear' => FALSE,
+        ]
+      );
+    }, $normalized['value']);
+
+    // Mock the field array similar to the other fields.
+    // @see Drupal\hal\Normalizer\FieldItemNormalizer for an example of this.
+    return array(
+      $field_item->getfieldDefinition()->getName() => [$normalized],
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function supportsDenormalization($data, $type, $format = NULL) {
+    return FALSE;
+  }
+
+  /**
+   * Extract the metatag overrides from the field item.
+   *
+   * @param \Drupal\Core\Field\FieldItemInterface $item
+   *   The field item whose internal data format needs converting for use.
+   *
+   * @return array
+   *   Return an array of metatag information, or an empty array if the field is
+   *   empty.
+   */
+  protected function getFieldValues(FieldItemInterface $item) {
+    $values = $item->getValue();
+    // Get serialized value and break it into an array of tags with values.
+    $serialized_value = $values['value'];
+
+    if (!empty($serialized_value)) {
+      $values['value'] = unserialize($serialized_value);
+    }
+
+    return $values;
+  }
+
+}
