diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
index cfbd971611..92fad1e39d 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php
@@ -23,7 +23,6 @@
    * {@inheritdoc}
    */
   protected static $patchProtectedFieldNames = [
-    'uid',
     'created',
     'changed',
     'promote',
diff --git a/core/modules/serialization/serialization.services.yml b/core/modules/serialization/serialization.services.yml
index 3e47b005cb..3607182ee2 100644
--- a/core/modules/serialization/serialization.services.yml
+++ b/core/modules/serialization/serialization.services.yml
@@ -33,6 +33,7 @@ services:
       # this modules generic field item normalizer.
       # @todo Find a better way for this in https://www.drupal.org/node/2575761.
       - { name: normalizer, priority: 8 }
+    arguments: ['@entity.repository']
   serialization.normalizer.field_item:
     class: Drupal\serialization\Normalizer\FieldItemNormalizer
     tags:
diff --git a/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php b/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
index 4706bf403d..ea2e020bf0 100644
--- a/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
+++ b/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php
@@ -2,12 +2,15 @@
 
 namespace Drupal\serialization\Normalizer;
 
+use Drupal\Core\Entity\EntityRepositoryInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 
 /**
  * Adds the file URI to embedded file entities.
  */
-class EntityReferenceFieldItemNormalizer extends ComplexDataNormalizer {
+class EntityReferenceFieldItemNormalizer extends FieldItemNormalizer {
 
   /**
    * The interface or class that this Normalizer supports.
@@ -17,6 +20,23 @@ class EntityReferenceFieldItemNormalizer extends ComplexDataNormalizer {
   protected $supportedInterfaceOrClass = EntityReferenceItem::class;
 
   /**
+   * The entity repository.
+   *
+   * @var \Drupal\Core\Entity\EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
+  /**
+   * Constructs a EntityReferenceFieldItemNormalizer object.
+   *
+   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+   *   The entity repository.
+   */
+  public function __construct(EntityRepositoryInterface $entity_repository) {
+    $this->entityRepository = $entity_repository;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function normalize($field_item, $format = NULL, array $context = []) {
@@ -35,8 +55,32 @@ public function normalize($field_item, $format = NULL, array $context = []) {
         $values['url'] = $url;
       }
     }
-
     return $values;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function constructValue($data, $context) {
+    if (isset($data['target_uuid'])) {
+      /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $field_item */
+      $field_item = $context['target_instance'];
+      if (empty($data['target_uuid'])) {
+        throw new InvalidArgumentException(sprintf('If provided "target_uuid" cannot be empty for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName()));
+      }
+      $target_type = $field_item->getFieldDefinition()->getSetting('target_type');
+      if (!empty($data['target_type']) && $target_type !== $data['target_type']) {
+        throw new UnexpectedValueException(sprintf('The field "%s" property "target_type" must be set to "%s" or omitted.', $field_item->getFieldDefinition()->getName(), $target_type));
+      }
+      if ($entity = $this->entityRepository->loadEntityByUuid($target_type, $data['target_uuid'])) {
+        return ['target_id' => $entity->id()];
+      }
+      else {
+        // Unable to load entity by uuid.
+        throw new InvalidArgumentException(sprintf('No "%s" entity found with UUID "%s" for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName()));
+      }
+    }
+    return parent::constructValue($data, $context);
+  }
+
 }
diff --git a/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php b/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
index d010a0494e..e0561a1003 100644
--- a/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
+++ b/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php
@@ -3,11 +3,18 @@
 namespace Drupal\Tests\serialization\Unit\Normalizer;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\Entity\EntityRepositoryInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
 use Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer;
 use Drupal\Tests\UnitTestCase;
 use Prophecy\Argument;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 use Symfony\Component\Serializer\Serializer;
 
 /**
@@ -38,10 +45,25 @@ class EntityReferenceFieldItemNormalizerTest extends UnitTestCase {
   protected $fieldItem;
 
   /**
+   * The mock entity repository.
+   *
+   * @var \Drupal\Core\Entity\EntityRepositoryInterface|\Prophecy\Prophecy\ObjectProphecy
+   */
+  protected $entityRepository;
+
+  /**
+   * The mock field definition.
+   *
+   * @var \Drupal\Core\Field\FieldDefinitionInterface|\Prophecy\Prophecy\ObjectProphecy
+   */
+  protected $fieldDefinition;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
-    $this->normalizer = new EntityReferenceFieldItemNormalizer();
+    $this->entityRepository = $this->prophesize(EntityRepositoryInterface::class);
+    $this->normalizer = new EntityReferenceFieldItemNormalizer($this->entityRepository->reveal());
 
     $this->serializer = $this->prophesize(Serializer::class);
     // Set up the serializer to return an entity property.
@@ -53,6 +75,9 @@ protected function setUp() {
     $this->fieldItem = $this->prophesize(EntityReferenceItem::class);
     $this->fieldItem->getIterator()
       ->willReturn(new \ArrayIterator(['target_id' => []]));
+
+    $this->fieldDefinition = $this->prophesize(FieldDefinitionInterface::class);
+
   }
 
   /**
@@ -64,6 +89,14 @@ public function testSupportsNormalization() {
   }
 
   /**
+   * @covers ::supportsDenormalization
+   */
+  public function testSupportsDenormalization() {
+    $this->assertTrue($this->normalizer->supportsDenormalization([], EntityReferenceItem::class));
+    $this->assertFalse($this->normalizer->supportsDenormalization([], FieldItemInterface::class));
+  }
+
+  /**
    * @covers ::normalize
    */
   public function testNormalize() {
@@ -121,4 +154,149 @@ public function testNormalizeWithNoEntity() {
     $this->assertSame($expected, $normalized);
   }
 
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithTypeAndUuid() {
+    $data = [
+      'target_id' => ['value' => 'test'],
+      'target_type' => 'test_type',
+      'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+    ];
+
+    $entity = $this->prophesize(FieldableEntityInterface::class);
+    $entity->id()
+      ->willReturn('test')
+      ->shouldBeCalled();
+    $this->entityRepository
+      ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
+      ->willReturn($entity)
+      ->shouldBeCalled();
+
+    $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithUuidWithoutType() {
+    $data = [
+      'target_id' => ['value' => 'test'],
+      'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+    ];
+
+    $entity = $this->prophesize(FieldableEntityInterface::class);
+    $entity->id()
+      ->willReturn('test')
+      ->shouldBeCalled();
+    $this->entityRepository
+      ->loadEntityByUuid('test_type', $data['target_uuid'])
+      ->willReturn($entity)
+      ->shouldBeCalled();
+
+    $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithUuidWithIncorrectType() {
+    $this->setExpectedException(UnexpectedValueException::class, 'The field "field_reference" property "target_type" must be set to "test_type" or omitted.');
+
+    $data = [
+      'target_id' => ['value' => 'test'],
+      'target_type' => 'wrong_type',
+      'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
+    ];
+
+    $this->fieldDefinition
+      ->getName()
+      ->willReturn('field_reference')
+      ->shouldBeCalled();
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithTypeWithIncorrectUuid() {
+    $this->setExpectedException(InvalidArgumentException::class, 'No "test_type" entity found with UUID "unique-but-none-non-existent" for field "field_reference"');
+
+    $data = [
+      'target_id' => ['value' => 'test'],
+      'target_type' => 'test_type',
+      'target_uuid' => 'unique-but-none-non-existent',
+    ];
+    $this->entityRepository
+      ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
+      ->willReturn(NULL)
+      ->shouldBeCalled();
+    $this->fieldItem
+      ->getName()
+      ->willReturn('field_reference')
+      ->shouldBeCalled();
+
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithEmtpyUuid() {
+    $this->setExpectedException(InvalidArgumentException::class, 'If provided "target_uuid" cannot be empty for field "test_type".');
+
+    $data = [
+      'target_id' => ['value' => 'test'],
+      'target_type' => 'test_type',
+      'target_uuid' => '',
+    ];
+    $this->fieldItem
+      ->getName()
+      ->willReturn('field_reference')
+      ->shouldBeCalled();
+
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * @covers ::denormalize
+   */
+  public function testDenormalizeWithId() {
+    $data = [
+      'target_id' => ['value' => 'test'],
+    ];
+    $this->fieldItem->setValue($data)->shouldBeCalled();
+
+    $this->assertDenormalize($data);
+  }
+
+  /**
+   * Asserts denormalization process is correct for give data.
+   *
+   * @param array $data
+   *   The data to denormalize.
+   */
+  protected function assertDenormalize(array $data) {
+    $this->fieldItem->getParent()
+      ->willReturn($this->prophesize(FieldItemListInterface::class)->reveal());
+    $this->fieldItem->getFieldDefinition()->willReturn($this->fieldDefinition->reveal());
+    if (!empty($data['target_uuid'])) {
+      $this->fieldDefinition
+        ->getSetting('target_type')
+        ->willReturn('test_type')
+        ->shouldBeCalled();
+    }
+
+    $context = ['target_instance' => $this->fieldItem->reveal()];
+    $denormalized = $this->normalizer->denormalize($data, EntityReferenceItem::class, 'json', $context);
+    $this->assertSame($context['target_instance'], $denormalized);
+  }
+
 }
