 core/modules/media/media.module                    | 16 ++++
 core/modules/media/media.services.yml              |  6 ++
 .../src/Kernel/MediaEntitiesNormalizerTest.php     | 95 ++++++++++++++++++++++
 .../media/tests/src/Kernel/MediaResourceTest.php   | 47 +++++++++++
 4 files changed, 164 insertions(+)

diff --git a/core/modules/media/media.module b/core/modules/media/media.module
index eeb2ac1..ea6bc01 100644
--- a/core/modules/media/media.module
+++ b/core/modules/media/media.module
@@ -114,3 +114,19 @@ function template_preprocess_media(array &$variables) {
     $variables['content'][$key] = $variables['elements'][$key];
   }
 }
+
+/**
+ * Implements hook_rest_resource_alter().
+ *
+ * The normalization of Media and Media Type entities was never considered
+ * during their development. Rather than allowing them to fall back to defaults
+ * for their normalizations (and hence serializations), this excludes them from
+ * being exposed as REST resources. This is done to ensure we don't let clients
+ * be developed against the default normalizations, which are known to contain
+ * gaps especially for file handling, and hence are guaranteed to break BC.
+ *
+ * @todo Remove this in https://www.drupal.org/node/2895573
+ */
+function media_rest_resource_alter(&$definitions) {
+  unset($definitions['entity:media'], $definitions['entity:media_type']);
+}
diff --git a/core/modules/media/media.services.yml b/core/modules/media/media.services.yml
index f22f90a..b61f7d2 100644
--- a/core/modules/media/media.services.yml
+++ b/core/modules/media/media.services.yml
@@ -8,3 +8,9 @@ services:
     arguments: ['@entity_type.manager']
     tags:
       - { name: access_check, applies_to: _access_media_revision }
+
+  # @todo Remove this in https://www.drupal.org/node/2895573
+  serializer.normalizer.media:
+    class: Drupal\media\Normalizer\MediaEntitiesNormalizer
+    tags:
+      - { name: normalizer, priority: 1000 }
diff --git a/core/modules/media/tests/src/Kernel/MediaEntitiesNormalizerTest.php b/core/modules/media/tests/src/Kernel/MediaEntitiesNormalizerTest.php
new file mode 100644
index 0000000..d227631
--- /dev/null
+++ b/core/modules/media/tests/src/Kernel/MediaEntitiesNormalizerTest.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Drupal\Tests\media\Kernel;
+
+use Drupal\Component\Serialization\Json;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\media\Entity\Media;
+use Drupal\media\Entity\MediaType;
+use Drupal\Tests\media\Functional\MediaFunctionalTestCreateMediaTypeTrait;
+use Symfony\Component\Serializer\Exception\UnsupportedException;
+
+/**
+ * @coversDefaultClass \Drupal\media\Normalizer\MediaEntitiesNormalizer
+ * @group media
+ *
+ * @todo Remove this in https://www.drupal.org/node/2895573
+ */
+class MediaEntitiesNormalizerTest extends KernelTestBase {
+
+  use MediaFunctionalTestCreateMediaTypeTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'serialization',
+    'rest',
+    'media',
+    'media_test_source',
+    'field',
+    'image',
+    'user',
+    'file',
+  ];
+
+  /**
+   * @covers ::normalize
+   * @dataProvider providerTestNormalize
+   */
+  public function testNormalize($entity_type_id, $operation) {
+    $this->setExpectedException(UnsupportedException::class, "Normalizing $entity_type_id entities is not yet supported.");
+
+    $media_type = $this->createMediaType();
+    if ($entity_type_id === 'media') {
+      $media = Media::create([
+        'bundle' => $media_type->id(),
+        'name' => 'Unnamed',
+      ]);
+    }
+    $entity_under_test = $entity_type_id === 'media' ? $media : $media_type;
+
+    $this->container->get('serializer')->$operation($entity_under_test, 'json');
+  }
+
+  public function providerTestNormalize() {
+    return [
+      'normalize Media' => ['media', 'normalize'],
+      'serialize Media' => ['media', 'serialize'],
+      'normalize Media Type' => ['media_type', 'normalize'],
+      'serialize Media Type' => ['media_type', 'serialize'],
+    ];
+  }
+
+  /**
+   * @covers ::denormalize
+   * @dataProvider providerTestDenormalize
+   */
+  public function testDenormalize($entity_type_id, $operation) {
+    $this->setExpectedException(UnsupportedException::class, "Denormalizing $entity_type_id entities is not yet supported.");
+
+    $data = [];
+    $class = MediaType::class;
+    if ($entity_type_id === 'media') {
+      $media_type = $this->createMediaType();
+      $data = ['bundle' => $media_type->id()];
+      $class = Media::class;
+    }
+
+    if ($operation === 'deserialize') {
+      $data = Json::encode($data);
+    }
+
+    $this->container->get('serializer')->$operation($data, $class, 'json');
+  }
+
+  public function providerTestDenormalize() {
+    return [
+      'denormalize Media' => ['media', 'denormalize'],
+      'deserialize Media' => ['media', 'deserialize'],
+      'denormalize Media Type' => ['media_type', 'denormalize'],
+      'deserialize Media Type' => ['media_type', 'deserialize'],
+    ];
+  }
+
+}
diff --git a/core/modules/media/tests/src/Kernel/MediaResourceTest.php b/core/modules/media/tests/src/Kernel/MediaResourceTest.php
new file mode 100644
index 0000000..0623257
--- /dev/null
+++ b/core/modules/media/tests/src/Kernel/MediaResourceTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\Tests\media\Kernel;
+
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\rest\Entity\RestResourceConfig;
+use Drupal\rest\RestResourceConfigInterface;
+
+/**
+ * @group media
+ *
+ * @todo Remove this in https://www.drupal.org/node/2895573
+ */
+class MediaResourceTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['serialization', 'rest', 'media'];
+
+  /**
+   * @dataProvider providerTestEnableMediaEntityType
+   */
+  public function testEnableMediaResource($entity_type_id) {
+    $this->setExpectedException(PluginNotFoundException::class, 'The "entity:' . $entity_type_id . '" plugin does not exist.');
+    RestResourceConfig::create([
+      'id' => 'entity.' . $entity_type_id,
+      'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
+      'configuration' => [
+        'methods' => ['GET'],
+        'formats' => ['json'],
+        'authentication' => ['cookie'],
+      ],
+    ])
+      ->enable()
+      ->save();
+  }
+
+  public function providerTestEnableMediaEntityType() {
+    return [
+      ['media'],
+      ['media_type'],
+    ];
+  }
+
+}
