diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index e3b2b9e1d091250ce5262240934a024dd4377cc4..349835d0fd0c49d2be6ba5eb0d29ff142a1161e8 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -235,15 +235,9 @@ config_dependencies:
 config_entity:
   type: mapping
   mapping:
-    id:
-      type: string
-      label: 'ID'
     uuid:
       type: string
       label: 'UUID'
-    label:
-      type: label
-      label: 'Label'
     langcode:
       type: string
       label: 'Default language'
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index 15eba92e2218cb8905a3d84c47e30d7a571fed99..7439b853f517e619a080cefc0d484a679832c15d 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Config\Schema\SchemaIncompleteException;
 use Drupal\Core\Entity\Entity;
 use Drupal\Core\Config\ConfigDuplicateUUIDException;
 use Drupal\Core\Entity\EntityStorageInterface;
@@ -240,19 +241,35 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b)
    * {@inheritdoc}
    */
   public function toArray() {
-    // Configuration objects do not have a schema. Extract all key names from
-    // class properties.
-    $class_info = new \ReflectionClass($this);
     $properties = array();
-    foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
-      $name = $property->getName();
-      $properties[$name] = $this->get($name);
+    $config_name = $this->getEntityType()->getConfigPrefix() . '.' . $this->id();
+    $definition = $this->getTypedConfig()->getDefinition($config_name);
+    if (!isset($definition['mapping'])) {
+      throw new SchemaIncompleteException(String::format('Incomplete or missing schema for @config_name', array('@config_name' => $config_name)));
+    }
+    $id_key = $this->getEntityType()->getKey('id');
+    foreach (array_keys($definition['mapping']) as $name) {
+      // Special handling for IDs so that computed compound IDs work.
+      // @see \Drupal\entity\EntityDisplayBase::id()
+      if ($name == $id_key) {
+        $properties[$name] = $this->id();
+      }
+      else {
+        $properties[$name] = $this->get($name);
+      }
     }
-    // Add protected dependencies property.
-    $properties['dependencies'] = $this->dependencies;
     return $properties;
   }
 
+  /**
+   * Gets the typed config manager.
+   *
+   * @return \Drupal\Core\Config\TypedConfigManagerInterface
+   */
+  protected function getTypedConfig() {
+    return \Drupal::service('config.typed');
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/block/config/schema/block.schema.yml b/core/modules/block/config/schema/block.schema.yml
index 9e4508b4c559c9b712567fa4f9279d9bb762223d..fdf50f555afc4d548bc18d64a237a997eaf44e5f 100644
--- a/core/modules/block/config/schema/block.schema.yml
+++ b/core/modules/block/config/schema/block.schema.yml
@@ -4,6 +4,9 @@ block.block.*:
   type: config_entity
   label: 'Block'
   mapping:
+    id:
+      type: string
+      label: 'ID'
     theme:
       type: string
       label: 'Theme'
diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php
index de6c9711fe791ea6682eb66c863b7be2e506dfa8..3f0903b86ce07bc1f8571bb46fdf50b42ba7557a 100644
--- a/core/modules/block/src/Entity/Block.php
+++ b/core/modules/block/src/Entity/Block.php
@@ -33,8 +33,7 @@
  *   admin_permission = "administer blocks",
  *   fieldable = FALSE,
  *   entity_keys = {
- *     "id" = "id",
- *     "label" = "label"
+ *     "id" = "id"
  *   },
  *   links = {
  *     "delete-form" = "block.admin_block_delete",
@@ -134,25 +133,6 @@ public function label() {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'theme',
-      'region',
-      'weight',
-      'plugin',
-      'settings',
-      'visibility',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * Sorts active blocks by weight; sorts inactive blocks by name.
    */
diff --git a/core/modules/block/src/Tests/BlockStorageUnitTest.php b/core/modules/block/src/Tests/BlockStorageUnitTest.php
index 65d67f6398da1fbcfec15aadb83d60ab3c5a15c9..ab5496cf59b27abb0ac1243e68aa61d4d7008878 100644
--- a/core/modules/block/src/Tests/BlockStorageUnitTest.php
+++ b/core/modules/block/src/Tests/BlockStorageUnitTest.php
@@ -90,13 +90,15 @@ protected function createTests() {
 
     // Ensure that default values are filled in.
     $expected_properties = array(
-      'id' => 'test_block',
-      'weight' => NULL,
-      'status' => TRUE,
       'langcode' => \Drupal::languageManager()->getDefaultLanguage()->id,
+      'status' => TRUE,
       'dependencies' => array('module' => array('block_test'), 'theme' => array('stark')),
+      'id' => 'test_block',
       'theme' => 'stark',
       'region' => '-1',
+      'weight' => NULL,
+      'provider' => NULL,
+      'visibility' => NULL,
       'plugin' => 'test_html',
       'settings' => array(
         'id' => 'test_html',
@@ -108,8 +110,8 @@ protected function createTests() {
           'contexts' => array(),
         ),
       ),
-      'visibility' => NULL,
     );
+
     $this->assertIdentical($actual_properties, $expected_properties);
 
     $this->assertTrue($entity->getPlugin() instanceof TestHtmlBlock, 'The entity has an instance of the correct block plugin.');
diff --git a/core/modules/block_content/config/schema/block_content.schema.yml b/core/modules/block_content/config/schema/block_content.schema.yml
index d24149492a84d3d0049dc5f9ffeb982baa3ac6df..2e7c338b2c0f6c2ff1c05104ea42d471fae12f9e 100644
--- a/core/modules/block_content/config/schema/block_content.schema.yml
+++ b/core/modules/block_content/config/schema/block_content.schema.yml
@@ -4,6 +4,12 @@ block_content.type.*:
   type: config_entity
   label: 'Custom block type settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     revision:
       type: integer
       label: 'Create new revision'
diff --git a/core/modules/breakpoint/config/schema/breakpoint.schema.yml b/core/modules/breakpoint/config/schema/breakpoint.schema.yml
index 4a669145dfb20f4aafb886d60f57f495d9b18ad9..c44ef4c2268c6dec8d0e9468573062a8a2c4d36b 100644
--- a/core/modules/breakpoint/config/schema/breakpoint.schema.yml
+++ b/core/modules/breakpoint/config/schema/breakpoint.schema.yml
@@ -3,6 +3,12 @@ breakpoint.breakpoint.*.*.*:
   type: config_entity
   label: 'Defines the Breakpoint entity'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     name:
       type: string
       label: 'Machine name'
@@ -29,6 +35,12 @@ breakpoint.breakpoint_group.*.*.*:
   type: config_entity
   label: 'Breakpoint group settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     name:
       type: string
       label: 'Machine name'
diff --git a/core/modules/breakpoint/src/Entity/BreakpointGroup.php b/core/modules/breakpoint/src/Entity/BreakpointGroup.php
index 02d6e29e504e66dbae84a8a59fa5aefdcb307b53..0b585e25974380a52fabfaa5f2792d5c87742294 100644
--- a/core/modules/breakpoint/src/Entity/BreakpointGroup.php
+++ b/core/modules/breakpoint/src/Entity/BreakpointGroup.php
@@ -211,29 +211,6 @@ public function getBreakpointById($id) {
     return FALSE;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $names = array(
-      'id',
-      'uuid',
-      'name',
-      'label',
-      'breakpoint_ids',
-      'source',
-      'sourceType',
-      'status',
-      'langcode',
-      'dependencies',
-    );
-    $properties = array();
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index d3522acfbb04198108d9aec7fbc8dc45e2ac7351..1c44234a741a56ca90762658e01467db899bfbdd 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -120,7 +120,7 @@ function comment_uri(CommentInterface $comment) {
 function comment_entity_extra_field_info() {
   $return = array();
   foreach (CommentType::loadMultiple() as $comment_type) {
-    $return['comment'][$comment_type->id] = array(
+    $return['comment'][$comment_type->id()] = array(
       'form' => array(
         'author' => array(
           'label' => t('Author'),
diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml
index 2ad9b13b17343fe30d3a640dcdf48c1cccbac98d..7a51d4f38040ae50f0605686954f13193f82802d 100644
--- a/core/modules/comment/config/schema/comment.schema.yml
+++ b/core/modules/comment/config/schema/comment.schema.yml
@@ -47,6 +47,12 @@ comment.type.*:
   type: config_entity
   label: 'Comment type settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     target_entity_type_id:
       type: string
       label: 'Target Entity Type ID'
diff --git a/core/modules/comment/src/CommentTypeForm.php b/core/modules/comment/src/CommentTypeForm.php
index 2454a875c7051280c01e5b1442426d4a1882e6bc..1ca8165e2e7cffdf670637e810e650fb612133ea 100644
--- a/core/modules/comment/src/CommentTypeForm.php
+++ b/core/modules/comment/src/CommentTypeForm.php
@@ -82,7 +82,7 @@ public function form(array $form, array &$form_state) {
 
     $form['description'] = array(
       '#type' => 'textarea',
-      '#default_value' => $comment_type->description,
+      '#default_value' => $comment_type->getDescription(),
       '#description' => t('Describe this comment type. The text will be displayed on the <em>Comment types</em> administration overview page'),
       '#title' => t('Description'),
     );
diff --git a/core/modules/comment/src/Entity/CommentType.php b/core/modules/comment/src/Entity/CommentType.php
index 4d7dd1df4e604e2311bec0bcdc41476d9411b36a..3b65bb3e1f291ee48391c200cb4db110659de362 100644
--- a/core/modules/comment/src/Entity/CommentType.php
+++ b/core/modules/comment/src/Entity/CommentType.php
@@ -47,28 +47,28 @@ class CommentType extends ConfigEntityBundleBase implements CommentTypeInterface
    *
    * @var string
    */
-  public $id;
+  protected $id;
 
   /**
    * The comment type label.
    *
    * @var string
    */
-  public $label;
+  protected $label;
 
   /**
    * The description of the comment type.
    *
    * @var string
    */
-  public $description;
+  protected $description;
 
   /**
    * The target entity type.
    *
    * @var string
    */
-  public $target_entity_type_id;
+  protected $target_entity_type_id;
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/config/src/Tests/ConfigDiffTest.php b/core/modules/config/src/Tests/ConfigDiffTest.php
index 03902e4938d3c69762c67dfb0e6ec5881ecb2d5d..fc9dc408d5d42194fd3d4cf56269ae9e230dce59 100644
--- a/core/modules/config/src/Tests/ConfigDiffTest.php
+++ b/core/modules/config/src/Tests/ConfigDiffTest.php
@@ -111,11 +111,12 @@ function testDiff() {
 
     $diff = \Drupal::service('config.manager')->diff($active, $staging, 'config_test.dynamic.' . $new_test_entity_id, $config_name);
     $edits = $diff->getEdits();
-    $this->assertEqual($edits[0]->type, 'change',  'The second item in the diff is a copy.');
-    $this->assertEqual($edits[0]->orig, array('id: ' . $new_test_entity_id));
-    $this->assertEqual($edits[0]->closing, array('id: ' . $test_entity_id));
-    $this->assertEqual($edits[1]->type, 'copy',  'The second item in the diff is a copy.');
-    $this->assertEqual(count($edits), 2, 'There are two items in the diff.');
+    $this->assertEqual($edits[0]->type, 'copy',  'The first item in the diff is a copy.');
+    $this->assertEqual($edits[1]->type, 'change',  'The second item in the diff is a change.');
+    $this->assertEqual($edits[1]->orig, array('id: ' . $new_test_entity_id));
+    $this->assertEqual($edits[1]->closing, array('id: ' . $test_entity_id));
+    $this->assertEqual($edits[2]->type, 'copy',  'The third item in the diff is a copy.');
+    $this->assertEqual(count($edits), 3, 'There are three items in the diff.');
   }
 
   /**
diff --git a/core/modules/config/src/Tests/ConfigEntityTest.php b/core/modules/config/src/Tests/ConfigEntityTest.php
index fc079f4afb3e1318e631485ed83dd77d39ba9d76..4a1bd1b2c715d585d31c328590bf7e42999472a5 100644
--- a/core/modules/config/src/Tests/ConfigEntityTest.php
+++ b/core/modules/config/src/Tests/ConfigEntityTest.php
@@ -46,7 +46,6 @@ function testCRUD() {
     $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->id;
     // Verify default properties on a newly created empty entity.
     $empty = entity_create('config_test');
-    $this->assertIdentical($empty->id, NULL);
     $this->assertTrue($empty->uuid);
     $this->assertIdentical($empty->label, NULL);
     $this->assertIdentical($empty->style, NULL);
@@ -105,7 +104,6 @@ function testCRUD() {
       'label' => $this->randomString(),
       'style' => $this->randomName(),
     ));
-    $this->assertIdentical($config_test->id, $expected['id']);
     $this->assertTrue($config_test->uuid);
     $this->assertNotEqual($config_test->uuid, $empty->uuid);
     $this->assertIdentical($config_test->label, $expected['label']);
@@ -159,7 +157,7 @@ function testCRUD() {
     try {
       $id_length_config_test->save();
       $this->pass(String::format("config_test entity with ID length @length was saved.", array(
-        '@length' => strlen($id_length_config_test->id))
+        '@length' => strlen($id_length_config_test->id()))
       ));
     }
     catch (ConfigEntityIdLengthException $e) {
@@ -173,7 +171,7 @@ function testCRUD() {
     try {
       $id_length_config_test->save();
       $this->pass(String::format("config_test entity with ID length @length was saved.", array(
-        '@length' => strlen($id_length_config_test->id),
+        '@length' => strlen($id_length_config_test->id()),
       )));
     }
     catch (ConfigEntityIdLengthException $e) {
@@ -187,13 +185,13 @@ function testCRUD() {
     try {
       $status = $id_length_config_test->save();
       $this->fail(String::format("config_test entity with ID length @length exceeding the maximum allowed length of @max saved successfully", array(
-        '@length' => strlen($id_length_config_test->id),
+        '@length' => strlen($id_length_config_test->id()),
         '@max' => static::MAX_ID_LENGTH,
       )));
     }
     catch (ConfigEntityIdLengthException $e) {
       $this->pass(String::format("config_test entity with ID length @length exceeding the maximum allowed length of @max failed to save", array(
-        '@length' => strlen($id_length_config_test->id),
+        '@length' => strlen($id_length_config_test->id()),
         '@max' => static::MAX_ID_LENGTH,
       )));
     }
@@ -221,7 +219,7 @@ function testCRUD() {
       $this->assertIdentical($config_test->getOriginalId(), $old_id);
 
       // Rename.
-      $config_test->id = $new_id;
+      $config_test->set('id', $new_id);
       $this->assertIdentical($config_test->id(), $new_id);
       $status = $config_test->save();
       $this->assertIdentical($status, SAVED_UPDATED);
diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php
index b95a666c4a2e82d4d2c6328486528a87ddaa1dc2..6f3bb2c5a48aefbb89a4429ed9f9d17dd06cef4f 100644
--- a/core/modules/config/src/Tests/ConfigImportUITest.php
+++ b/core/modules/config/src/Tests/ConfigImportUITest.php
@@ -56,15 +56,15 @@ function testImport() {
 
     // Create new config entity.
     $original_dynamic_data = array(
+      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
+      'langcode' => \Drupal::languageManager()->getDefaultLanguage()->id,
+      'status' => TRUE,
+      'dependencies' => array(),
       'id' => 'new',
       'label' => 'New',
       'weight' => 0,
       'style' => '',
       'test_dependencies' => array(),
-      'status' => TRUE,
-      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
-      'langcode' => \Drupal::languageManager()->getDefaultLanguage()->id,
-      'dependencies' => array(),
       'protected_property' => '',
     );
     $staging->write($dynamic_name, $original_dynamic_data);
@@ -349,31 +349,31 @@ function testImportErrorLog() {
     $uuid = $this->container->get('uuid');
 
     $values_primary = array(
+      'uuid' => $uuid->generate(),
+      'langcode' => 'en',
+      'status' => TRUE,
+      'dependencies' => array(),
       'id' => 'primary',
       'label' => 'Primary',
       'weight' => 0,
       'style' => NULL,
       'test_dependencies' => array(),
-      'status' => TRUE,
-      'uuid' => $uuid->generate(),
-      'langcode' => 'en',
-      'dependencies' => array(),
       'protected_property' => null,
     );
     $staging->write($name_primary, $values_primary);
     $values_secondary = array(
-      'id' => 'secondary',
-      'label' => 'Secondary Sync',
-      'weight' => 0,
-      'style' => NULL,
-      'test_dependencies' => array(),
-      'status' => TRUE,
       'uuid' => $uuid->generate(),
       'langcode' => 'en',
+      'status' => TRUE,
       // Add a dependency on primary, to ensure that is synced first.
       'dependencies' => array(
         'entity' => array($name_primary),
       ),
+      'id' => 'secondary',
+      'label' => 'Secondary Sync',
+      'weight' => 0,
+      'style' => NULL,
+      'test_dependencies' => array(),
       'protected_property' => null,
     );
     $staging->write($name_secondary, $values_secondary);
diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php
index 21ce402e7ced90dc5adb32c669e90bef4068fdf5..ca4d7044dde63b4e70cd9155ed331f4b46c047fd 100644
--- a/core/modules/config/src/Tests/ConfigImporterTest.php
+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -170,15 +170,15 @@ function testNew() {
 
     // Create new config entity.
     $original_dynamic_data = array(
+      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
+      'langcode' => \Drupal::languageManager()->getDefaultLanguage()->id,
+      'status' => TRUE,
+      'dependencies' => array(),
       'id' => 'new',
       'label' => 'New',
       'weight' => 0,
       'style' => '',
       'test_dependencies' => array(),
-      'status' => TRUE,
-      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
-      'langcode' => \Drupal::languageManager()->getDefaultLanguage()->id,
-      'dependencies' => array(),
       'protected_property' => '',
     );
     $staging->write($dynamic_name, $original_dynamic_data);
diff --git a/core/modules/config/src/Tests/ConfigSchemaTest.php b/core/modules/config/src/Tests/ConfigSchemaTest.php
index 14161bb5ebacef1da7959909fdba34440533273f..ca5eabaaa80b2efda2dd7dab7e3a66c41e799577 100644
--- a/core/modules/config/src/Tests/ConfigSchemaTest.php
+++ b/core/modules/config/src/Tests/ConfigSchemaTest.php
@@ -135,12 +135,8 @@ function testSchemaMapping() {
     $expected['label'] = 'Image style';
     $expected['class'] = '\Drupal\Core\Config\Schema\Mapping';
     $expected['mapping']['name']['type'] = 'string';
-    $expected['mapping']['id']['label'] = 'ID';
-    $expected['mapping']['id']['type'] = 'string';
     $expected['mapping']['uuid']['type'] = 'string';
     $expected['mapping']['uuid']['label'] = 'UUID';
-    $expected['mapping']['label']['type'] = 'label';
-    $expected['mapping']['label']['label'] = 'Label';
     $expected['mapping']['langcode']['type'] = 'string';
     $expected['mapping']['langcode']['label'] = 'Default language';
     $expected['mapping']['status']['type'] = 'boolean';
@@ -148,6 +144,8 @@ function testSchemaMapping() {
     $expected['mapping']['dependencies']['type'] = 'config_dependencies';
     $expected['mapping']['dependencies']['label'] = 'Dependencies';
     $expected['mapping']['name']['type'] = 'string';
+    $expected['mapping']['label']['type'] = 'label';
+    $expected['mapping']['label']['label'] = 'Label';
     $expected['mapping']['effects']['type'] = 'sequence';
     $expected['mapping']['effects']['sequence'][0]['type'] = 'mapping';
     $expected['mapping']['effects']['sequence'][0]['mapping']['id']['type'] = 'string';
diff --git a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
index 6a585d3e09801cf4cea27de45d99509afdff32fc..904fb695c16816ec65d43ff8fbbb5fba829089dd 100644
--- a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
+++ b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
@@ -1,34 +1,23 @@
 # Schema for the configuration files of the Configuration Test module.
 
-config_test.dynamic.*:
-  type: mapping
-  label: 'Config test entity'
+config_test_dynamic:
+  type: config_entity
   mapping:
     id:
       type: string
-      label: 'Machine name'
+      label: 'ID'
     label:
       type: label
       label: 'Label'
-    weight:
-      type: integer
-      label: 'Weight'
-    style:
-      type: string
-      label: 'Image style'
-    protected_property:
-      type: string
-      label: 'Protected property'
-
-config_test_dynamic:
-  type: config_entity
-  mapping:
     weight:
       type: integer
       label: 'Weight'
     style:
       type: string
       label: 'style'
+    test_dependencies:
+      type: config_dependencies
+      label: 'Configuration dependencies'
     protected_property:
       type: string
       label: 'Protected property'
@@ -41,6 +30,24 @@ config_test.dynamic.*.*:
   type: config_test_dynamic
   label: 'Config test dynamic settings'
 
+config_test.query.*:
+  type: config_entity
+  mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
+    array:
+      type: sequence
+      label: 'Array'
+      sequence:
+        - type: string
+    number:
+      type: integer
+      label: 'number'
+
 config_test.types:
   type: mapping
   label: 'Configuration type'
diff --git a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php
index 07ec50a125fc641dfed3f855af76dfc41376bb00..b5f2deadf3260077dc93999d51cf82cf4644a266 100644
--- a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php
+++ b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php
@@ -48,7 +48,7 @@ class ConfigTest extends ConfigEntityBase implements ConfigTestInterface {
    *
    * @var string
    */
-  public $id;
+  protected $id;
 
   /**
    * The human-readable name of the configuration entity.
@@ -85,20 +85,6 @@ class ConfigTest extends ConfigEntityBase implements ConfigTestInterface {
    */
   protected $protected_property;
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $protected_names = array(
-      'protected_property',
-    );
-    foreach ($protected_names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
    */
diff --git a/core/modules/contact/config/schema/contact.schema.yml b/core/modules/contact/config/schema/contact.schema.yml
index 5443bf36f6450e6e0765c89afd8e0f370ab5a2e7..0ef4c2e9dacafd2c01e485f4a0146e4df4de3622 100644
--- a/core/modules/contact/config/schema/contact.schema.yml
+++ b/core/modules/contact/config/schema/contact.schema.yml
@@ -4,6 +4,12 @@ contact.category.*:
   type: config_entity
   label: 'Contact category'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     recipients:
       type: sequence
       label: 'Recipients'
diff --git a/core/modules/editor/src/Entity/Editor.php b/core/modules/editor/src/Entity/Editor.php
index d555db7d93338674aa27f26c4917376393c14e70..29f73506aa95e59582e934b81e3eed0cb68a9e69 100644
--- a/core/modules/editor/src/Entity/Editor.php
+++ b/core/modules/editor/src/Entity/Editor.php
@@ -176,21 +176,4 @@ public function setImageUploadSettings(array $image_upload_settings) {
     return $this;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'format',
-      'editor',
-      'settings',
-      'image_upload',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
 }
diff --git a/core/modules/entity/config/schema/entity.schema.yml b/core/modules/entity/config/schema/entity.schema.yml
index 4583093a2c4ed3e7d85acd6d4dcccafc213b9766..074d82a60c1279de44292859b143e1714df621da 100644
--- a/core/modules/entity/config/schema/entity.schema.yml
+++ b/core/modules/entity/config/schema/entity.schema.yml
@@ -33,6 +33,12 @@ entity.form_mode.*.*:
   type: config_entity
   label: 'Entity form mode settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     targetEntityType:
       type: string
       label: 'Target entity type'
@@ -45,6 +51,12 @@ entity.view_display.*.*.*:
   type: config_entity
   label: 'Entity display'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     targetEntityType:
       type: string
       label: 'Target entity type'
@@ -71,6 +83,9 @@ entity.form_display.*.*.*:
   type: config_entity
   label: 'Entity form display'
   mapping:
+    id:
+      type: string
+      label: 'ID'
     targetEntityType:
       type: string
       label: 'Target entity type'
@@ -80,9 +95,12 @@ entity.form_display.*.*.*:
     mode:
       type: string
       label: 'View or form mode machine name'
+    status:
+      type: boolean
+      label: 'Enabled'
     content:
       type: sequence
-      label: 'Field form display formatters'
+      label: 'Field display formatters'
       sequence:
         - type: entity_form_display.field.[type]
     hidden:
@@ -91,6 +109,9 @@ entity.form_display.*.*.*:
       sequence:
         - type: boolean
           label: 'Component'
+    dependencies:
+      type: config_dependencies
+      label: 'Dependencies'
 
 # Default schema for entity display field with undefined type.
 entity_view_display.field.*:
diff --git a/core/modules/entity/src/EntityDisplayBase.php b/core/modules/entity/src/EntityDisplayBase.php
index 34dc8151cf4ffbb1a0f31ca0f92cfeb5356d7339..a9b99d26534e5feef151bff44a7215dea833255e 100644
--- a/core/modules/entity/src/EntityDisplayBase.php
+++ b/core/modules/entity/src/EntityDisplayBase.php
@@ -200,23 +200,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    * {@inheritdoc}
    */
   public function toArray() {
-    $names = array(
-      'uuid',
-      'targetEntityType',
-      'bundle',
-      'mode',
-      'content',
-      'hidden',
-      'status',
-      'dependencies'
-    );
-    $properties = array(
-      'id' => $this->id(),
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-
+    $properties = parent::toArray();
     // Do not store options for fields whose display is not set to be
     // configurable.
     foreach ($this->getFieldDefinitions() as $field_name => $definition) {
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index ff871bfcf40cf59bc6b3d84e7583918f7cf7eba7..a00c89e6e31e5eb3dbfb4d8139895dc85c9e16c3 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -12,6 +12,9 @@ field.field.*.*:
   type: config_entity
   label: 'Field'
   mapping:
+    id:
+      type: string
+      label: 'ID'
     name:
       type: string
       label: 'Name'
@@ -49,6 +52,12 @@ field.instance.*.*.*:
   type: config_entity
   label: 'Field instance'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     field_uuid:
       type: string
       label: 'Field UUID'
diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php
index 7bef0553ea8e243b1d813b6f8e2434eb71ef5add..6e0aa46554ff261349923d3b4b86887227aaf941 100644
--- a/core/modules/field/src/Entity/FieldConfig.php
+++ b/core/modules/field/src/Entity/FieldConfig.php
@@ -224,34 +224,6 @@ public function id() {
     return $this->entity_type . '.' . $this->name;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $names = array(
-      'uuid',
-      'status',
-      'langcode',
-      'name',
-      'entity_type',
-      'type',
-      'settings',
-      'module',
-      'locked',
-      'cardinality',
-      'translatable',
-      'indexes',
-      'dependencies',
-    );
-    $properties = array(
-      'id' => $this->id(),
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * Overrides \Drupal\Core\Entity\Entity::preSave().
    *
@@ -728,7 +700,10 @@ public function entityCount($as_bool = FALSE) {
    */
   public function __sleep() {
     // Only serialize properties from self::toArray().
-    return array_keys(array_intersect_key($this->toArray(), get_object_vars($this)));
+    $properties = array_keys(array_intersect_key($this->toArray(), get_object_vars($this)));
+    // Serialize $entityTypeId property so that toArray() works when waking up.
+    $properties[] = 'entityTypeId';
+    return $properties;
   }
 
   /**
diff --git a/core/modules/field/src/Entity/FieldInstanceConfig.php b/core/modules/field/src/Entity/FieldInstanceConfig.php
index 40fbbd229369e63da75692ef5ef2ed7601d77d04..11ab930f7956565fa156eac7a1280a917e4900da 100644
--- a/core/modules/field/src/Entity/FieldInstanceConfig.php
+++ b/core/modules/field/src/Entity/FieldInstanceConfig.php
@@ -272,29 +272,7 @@ public function id() {
    * {@inheritdoc}
    */
   public function toArray() {
-    $names = array(
-      'uuid',
-      'status',
-      'langcode',
-      'field_uuid',
-      'field_name',
-      'entity_type',
-      'bundle',
-      'label',
-      'description',
-      'required',
-      'default_value',
-      'default_value_function',
-      'settings',
-      'dependencies',
-    );
-    $properties = array(
-      'id' => $this->id(),
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-
+    $properties = parent::toArray();
     // Additionally, include the field type, that is needed to be able to
     // generate the field-type-dependant parts of the config schema.
     $properties['field_type'] = $this->getType();
@@ -672,7 +650,10 @@ public function targetBundle() {
    */
   public function __sleep() {
     // Only serialize properties from self::toArray().
-    return array_keys(array_intersect_key($this->toArray(), get_object_vars($this)));
+    $properties = array_keys(array_intersect_key($this->toArray(), get_object_vars($this)));
+    // Serialize $entityTypeId property so that toArray() works when waking up.
+    $properties[] = 'entityTypeId';
+    return $properties;
   }
 
   /**
diff --git a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
index ca06aab9a26fc6253df767670c78c985a61680ce..450b20f6f5b3599426bb38cf106f0457a291c134 100644
--- a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
+++ b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
@@ -64,14 +64,18 @@ public static function getInfo() {
    */
   public function setUp() {
     $this->entityTypeId = $this->randomName();
+    $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
 
     $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
 
     $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
 
+    $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
+
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
+    $container->set('config.typed', $this->typedConfigManager);
     \Drupal::setContainer($container);
 
     // Create a mock FieldConfig object.
@@ -139,12 +143,12 @@ public function testCalculateDependencies() {
    */
   public function testToArray() {
     $values = array('field_name' => $this->field->getName(), 'entity_type' => 'test_entity_type', 'bundle' => 'test_bundle');
-    $instance = new FieldInstanceConfig($values);
-    $export = $instance->toArray();
+    $instance = new FieldInstanceConfig($values, $this->entityTypeId);
+
     $expected = array(
       'id' => 'test_entity_type.test_bundle.field_test',
       'uuid' => NULL,
-      'status' => 1,
+      'status' => TRUE,
       'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
       'field_uuid' => NULL,
       'field_name' => 'field_test',
@@ -159,6 +163,19 @@ public function testToArray() {
       'dependencies' => array(),
       'field_type' => 'test_field',
     );
+    $this->entityManager->expects($this->any())
+       ->method('getDefinition')
+       ->with($this->entityTypeId)
+       ->will($this->returnValue($this->entityType));
+    $this->entityType->expects($this->once())
+      ->method('getKey')
+      ->with('id')
+      ->will($this->returnValue('id'));
+    $this->typedConfigManager->expects($this->once())
+      ->method('getDefinition')
+      ->will($this->returnValue(array('mapping' => array_fill_keys(array_keys($expected), ''))));
+
+    $export = $instance->toArray();
     $this->assertEquals($expected, $export);
   }
 }
diff --git a/core/modules/filter/src/Entity/FilterFormat.php b/core/modules/filter/src/Entity/FilterFormat.php
index 9598f77aa52e363f63bb69f677aa49aa1028f4af..944d5c7cd311b748c519290552b7a4408bfa9140 100644
--- a/core/modules/filter/src/Entity/FilterFormat.php
+++ b/core/modules/filter/src/Entity/FilterFormat.php
@@ -162,13 +162,9 @@ public function setFilterConfig($instance_id, array $configuration) {
    */
   public function toArray() {
     $properties = parent::toArray();
-    // @todo Make self::$weight and self::$cache protected and add them here.
-    $names = array(
-      'filters',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
+    // The 'roles' property is only used during install and should never
+    // actually be saved.
+    unset($properties['roles']);
     return $properties;
   }
 
diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml
index 824869601e99fd0461faf280af813ae790927d8f..2985696f9f42d39402e5cc5caefa83a4beedc04c 100644
--- a/core/modules/image/config/schema/image.schema.yml
+++ b/core/modules/image/config/schema/image.schema.yml
@@ -6,6 +6,9 @@ image.style.*:
   mapping:
     name:
       type: string
+    label:
+      type: label
+      label: 'Label'
     effects:
       type: sequence
       sequence:
diff --git a/core/modules/image/src/Entity/ImageStyle.php b/core/modules/image/src/Entity/ImageStyle.php
index 0338767d933eac82093c8ce843ecfd38f4bd8e29..ad415a91bc6dbc0d97e349d21bc5f5278d97eeff 100644
--- a/core/modules/image/src/Entity/ImageStyle.php
+++ b/core/modules/image/src/Entity/ImageStyle.php
@@ -354,20 +354,6 @@ public function addImageEffect(array $configuration) {
     return $configuration['uuid'];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'effects',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/language/config/schema/language.schema.yml b/core/modules/language/config/schema/language.schema.yml
index 584a7158252ffcda4506983d24b126a87f5dbc62..210a1e6afc7c035c897f8bd69053516f74c7cbaf 100644
--- a/core/modules/language/config/schema/language.schema.yml
+++ b/core/modules/language/config/schema/language.schema.yml
@@ -85,6 +85,12 @@ language.entity.*:
   type: config_entity
   label: 'Language'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     direction:
       type: integer
       label: 'Direction'
diff --git a/core/modules/migrate/src/Entity/Migration.php b/core/modules/migrate/src/Entity/Migration.php
index 5adea0904b33c35191e105a9145a2b76d9099fbe..c892ccb5fe22322b28c1f6f1f4391846a0988b99 100644
--- a/core/modules/migrate/src/Entity/Migration.php
+++ b/core/modules/migrate/src/Entity/Migration.php
@@ -339,4 +339,18 @@ public function checkRequirements() {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function toArray() {
+    // @todo Remove once migration config entities have schema
+    //   https://drupal.org/node/2183957.
+    $class_info = new \ReflectionClass($this);
+    foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
+      $name = $property->getName();
+      $properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
 }
diff --git a/core/modules/rdf/config/schema/rdf.schema.yml b/core/modules/rdf/config/schema/rdf.schema.yml
index 75b83ed616bc0d1ab02d726935f5f138c052794a..ac452a36125e66d9414452fef5acb4ae9c8e00df 100644
--- a/core/modules/rdf/config/schema/rdf.schema.yml
+++ b/core/modules/rdf/config/schema/rdf.schema.yml
@@ -4,6 +4,9 @@ rdf.mapping.*.*:
   type: config_entity
   label: 'RDF mapping'
   mapping:
+    id:
+      type: string
+      label: 'ID'
     targetEntityType:
       type: string
       label: 'Target entity type'
diff --git a/core/modules/rdf/src/Entity/RdfMapping.php b/core/modules/rdf/src/Entity/RdfMapping.php
index e5783b794bd4e3a9b0d675014f31fea023db6a59..76607ec4bc3c40ad14ae60671cf1030911dc906a 100644
--- a/core/modules/rdf/src/Entity/RdfMapping.php
+++ b/core/modules/rdf/src/Entity/RdfMapping.php
@@ -133,30 +133,6 @@ public function id() {
     return $this->targetEntityType . '.' . $this->bundle;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $names = array(
-      'uuid',
-      'targetEntityType',
-      'bundle',
-      'types',
-      'fieldMappings',
-    );
-    $properties = array(
-      'id' => $this->id(),
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    if (!empty($this->dependencies)) {
-      // Add protected dependencies property if set.
-      $properties['dependencies'] = $this->dependencies;
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php b/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php
index ed96b179abaf639c76e9cc82b2c66a892ba36657..7c3781805dbd3c6c28da43d6aa994a1cde529555 100644
--- a/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php
+++ b/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php
@@ -187,24 +187,6 @@ public function hasMappings() {
     return $mapping_found;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $names = array(
-      'id',
-      'uuid',
-      'label',
-      'mappings',
-      'breakpointGroup',
-    );
-    $properties = array();
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/search/config/schema/search.schema.yml b/core/modules/search/config/schema/search.schema.yml
index d4114e234469df3a4c95bc570f4c166e75ceef61..3be192c44b476c4dbde79445ef9f30ecb3808167 100644
--- a/core/modules/search/config/schema/search.schema.yml
+++ b/core/modules/search/config/schema/search.schema.yml
@@ -68,6 +68,12 @@ search.page.*:
   type: config_entity
   label: 'Search page'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     path:
       type: string
       label: 'Search page path'
diff --git a/core/modules/search/src/Entity/SearchPage.php b/core/modules/search/src/Entity/SearchPage.php
index f1b92cde22c29a2973020bd7bf59458bde504410..7341221b1b3a8bc775547ed74c283f1f495c85eb 100644
--- a/core/modules/search/src/Entity/SearchPage.php
+++ b/core/modules/search/src/Entity/SearchPage.php
@@ -166,23 +166,6 @@ public function getWeight() {
     return $this->weight;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'path',
-      'weight',
-      'plugin',
-      'configuration',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/shortcut/config/schema/shortcut.schema.yml b/core/modules/shortcut/config/schema/shortcut.schema.yml
index 0162d80961090ec2e87772281cc275aa38f47d86..daef4343351791a220afa610a41274c3889f126f 100644
--- a/core/modules/shortcut/config/schema/shortcut.schema.yml
+++ b/core/modules/shortcut/config/schema/shortcut.schema.yml
@@ -4,6 +4,12 @@ shortcut.set.*:
   type: config_entity
   label: 'Shortcut settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     links:
       type: sequence
       label: 'Shortcuts'
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index c3e3bc31c87168c9d180ff078a036a02650716da..537552443957f329c61e19acd2257e2b0c7b13b9 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -118,6 +118,12 @@ system.date_format.*:
   type: config_entity
   label: 'Date format'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     locked:
       type: boolean
       label: 'Locked'
@@ -278,6 +284,12 @@ system.menu.*:
   type: config_entity
   label: 'Menu'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     description:
       type: label
       label: 'Menu description'
@@ -289,6 +301,12 @@ system.action.*:
   type: config_entity
   label: 'System action'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     type:
       type: string
       label: 'Type'
diff --git a/core/modules/system/src/Entity/Action.php b/core/modules/system/src/Entity/Action.php
index 642933a289bb45a35337e504a09daf9d39f1fe14..e48f335c37ff3b81c508014235baa411b721fd18 100644
--- a/core/modules/system/src/Entity/Action.php
+++ b/core/modules/system/src/Entity/Action.php
@@ -148,20 +148,4 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b)
     return parent::sort($a, $b);
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'type',
-      'plugin',
-      'configuration',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
 }
diff --git a/core/modules/system/src/Entity/DateFormat.php b/core/modules/system/src/Entity/DateFormat.php
index 1016fbc540e2a37eb50e3812f6181bd950cbdce5..a7d689dba9a85636e62fc2f09607a46e378ec02b 100644
--- a/core/modules/system/src/Entity/DateFormat.php
+++ b/core/modules/system/src/Entity/DateFormat.php
@@ -68,21 +68,6 @@ class DateFormat extends ConfigEntityBase implements DateFormatInterface {
    */
   protected $locked = FALSE;
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'locked',
-      'pattern',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/system/src/Entity/Menu.php b/core/modules/system/src/Entity/Menu.php
index 2ea8dd18fde3406ddf6eae82c5ae1e36e2c1b9a7..756728fb84c53640d991af4d324709eaa961c325 100644
--- a/core/modules/system/src/Entity/Menu.php
+++ b/core/modules/system/src/Entity/Menu.php
@@ -57,22 +57,6 @@ class Menu extends ConfigEntityBase implements MenuInterface {
    */
   protected $locked = FALSE;
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    // @todo Make $description protected and include it here, see
-    //   https://drupal.org/node/2030645.
-    $names = array(
-      'locked',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/tour/config/schema/tour.schema.yml b/core/modules/tour/config/schema/tour.schema.yml
index d277cfe8f666b53cf711d60ed66bb0f0f141547d..5d0d85e605757a2a4e183eadf2bb7c0916e21394 100644
--- a/core/modules/tour/config/schema/tour.schema.yml
+++ b/core/modules/tour/config/schema/tour.schema.yml
@@ -4,6 +4,12 @@ tour.tour.*:
   type: config_entity
   label: 'Tour settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     module:
       type: string
       label: 'Providing module'
diff --git a/core/modules/tour/src/Entity/Tour.php b/core/modules/tour/src/Entity/Tour.php
index 1361942c25515007926537503189ff9586ce2d45..d8271ac5992cfa207251e59bb1763a4c4f92089a 100644
--- a/core/modules/tour/src/Entity/Tour.php
+++ b/core/modules/tour/src/Entity/Tour.php
@@ -120,21 +120,6 @@ public function getTips() {
     return array_values($tips);
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'routes',
-      'tips',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml
index 44762edf86f79369bfe67e35d75f7b77c7f6af78..69600fd20bf379aa575d4359c614f194ca4f064b 100644
--- a/core/modules/user/config/schema/user.schema.yml
+++ b/core/modules/user/config/schema/user.schema.yml
@@ -119,6 +119,12 @@ user.role.*:
   type: config_entity
   label: 'User role settings'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     weight:
       type: integer
       label: 'User role weight'
diff --git a/core/modules/views/config/schema/views.schema.yml b/core/modules/views/config/schema/views.schema.yml
index fba3ce45f6506c9b69ed229316d696dae958e000..8b837c2a247c034fbd279cd1491e9b31fec4ef3c 100644
--- a/core/modules/views/config/schema/views.schema.yml
+++ b/core/modules/views/config/schema/views.schema.yml
@@ -72,6 +72,12 @@ views.view.*:
   type: config_entity
   label: 'View'
   mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
     module:
       type: string
       label: 'Module'
diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index db5ba76104541eb2bcbd537bf10db80fe75c8154..00098b880ca164ff0abf7bfd95bc9ac31f1d6b76 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -240,32 +240,6 @@ public function &getDisplay($display_id) {
     return $this->display[$display_id];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function toArray() {
-    $names = array(
-      'base_field',
-      'base_table',
-      'core',
-      'description',
-      'status',
-      'display',
-      'label',
-      'module',
-      'id',
-      'tag',
-      'uuid',
-      'langcode',
-      'dependencies',
-    );
-    $properties = array();
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 4f718fc1bfa16a30b570e05e09d1c0445e66ada2..a824b3ab5fbf48e7f5e39740a16882956f305344 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -85,6 +85,13 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
    */
   protected $cacheBackend;
 
+  /**
+   * The mocked typed config manager.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $typedConfigManager;
+
   /**
    * {@inheritdoc}
    */
@@ -129,11 +136,14 @@ public function setUp() {
 
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
 
+    $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
+
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
     $container->set('language_manager', $this->languageManager);
     $container->set('cache.test', $this->cacheBackend);
+    $container->set('config.typed', $this->typedConfigManager);
     $container->setParameter('cache_bins', array('cache.test' => 'test'));
     \Drupal::setContainer($container);
 
@@ -431,14 +441,21 @@ public function testSort() {
    * @covers ::toArray
    */
   public function testToArray() {
+    $this->typedConfigManager->expects($this->once())
+      ->method('getDefinition')
+      ->will($this->returnValue(array('mapping' => array('id' => '', 'dependencies' => ''))));
     $properties = $this->entity->toArray();
     $this->assertInternalType('array', $properties);
-    $class_info = new \ReflectionClass($this->entity);
-    foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
-      $name = $property->getName();
-      $this->assertArrayHasKey($name, $properties);
-      $this->assertSame($this->entity->get($name), $properties[$name]);
-    }
+    $this->assertEquals(array('id' => $this->entity->id(), 'dependencies' => array()), $properties);
+  }
+
+  /**
+   * @covers ::toArray
+   *
+   * @expectedException \Drupal\Core\Config\Schema\SchemaIncompleteException
+   */
+  public function testToArrayFallback() {
+    $this->entity->toArray();
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 37019f50ebc58c397a16e645bef7087cc4cb6076..12c4823dc99cbe5c898cfccde6df44b406bdb58f 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -97,6 +97,13 @@ class ConfigEntityStorageTest extends UnitTestCase {
    */
   protected $cacheBackend;
 
+  /**
+   * The mocked typed config manager.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $typedConfigManager;
+
   /**
    * {@inheritdoc}
    */
@@ -167,8 +174,13 @@ protected function setUp() {
 
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
 
+    $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
+    $this->typedConfigManager->expects($this->any())
+      ->method('getDefinition')
+      ->will($this->returnValue(array('mapping' => array('id' => '', 'uuid' => '', 'dependencies' => ''))));
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
+    $container->set('config.typed', $this->typedConfigManager);
     $container->set('cache.test', $this->cacheBackend);
     $container->setParameter('cache_bins', array('cache.test' => 'test'));
     \Drupal::setContainer($container);
@@ -242,7 +254,7 @@ public function testSaveInsert(EntityInterface $entity) {
     $config_object->expects($this->atLeastOnce())
       ->method('isNew')
       ->will($this->returnValue(TRUE));
-    $config_object->expects($this->exactly(4))
+    $config_object->expects($this->exactly(3))
       ->method('set');
     $config_object->expects($this->once())
       ->method('save');
@@ -301,7 +313,7 @@ public function testSaveUpdate(EntityInterface $entity) {
     $config_object->expects($this->atLeastOnce())
       ->method('isNew')
       ->will($this->returnValue(FALSE));
-    $config_object->expects($this->exactly(4))
+    $config_object->expects($this->exactly(3))
       ->method('set');
     $config_object->expects($this->once())
       ->method('save');
@@ -361,7 +373,7 @@ public function testSaveRename(ConfigEntityInterface $entity) {
     $config_object->expects($this->atLeastOnce())
       ->method('isNew')
       ->will($this->returnValue(FALSE));
-    $config_object->expects($this->exactly(4))
+    $config_object->expects($this->exactly(3))
       ->method('set');
     $config_object->expects($this->once())
       ->method('save');