diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index e020a2e..309f201 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,20 +241,52 @@ 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);
+    try {
+      foreach ($this->getPropertiesFromSchema() as $name) {
+        $properties[$name] = $this->get($name);
+      }
+    }
+    catch (SchemaIncompleteException $e) {
+      // Some 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);
+      }
     }
-    // Add protected dependencies property.
-    $properties['dependencies'] = $this->dependencies;
     return $properties;
   }
 
   /**
+   * Gets the root properties of the configuration entity from its schema.
+   *
+   * @return array
+   *   An array of property names.
+   *
+   * @throws \Exception
+   */
+  protected function getPropertiesFromSchema() {
+    $config_name = $this->getEntityType()->getConfigPrefix() . '.' . $this->id();
+    $definition = $this->getTypedConfig()->getDefinition($config_name);
+    if (!isset($definition['mapping'])) {
+      throw new SchemaIncompleteException(String::format('Missing root mapping definition in config schema for !name', array('!name' => $config_name)));
+    }
+    return array_keys($definition['mapping']);
+  }
+
+  /**
+   * Gets the typed config manager.
+   *
+   * @return \Drupal\Core\Config\TypedConfigManagerInterface
+   */
+  protected function getTypedConfig() {
+    return \Drupal::service('config.typed');
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function preSave(EntityStorageInterface $storage) {
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
index f3ca94f..776c6ee 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
@@ -47,7 +47,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);
@@ -106,7 +105,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']);
@@ -160,7 +158,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) {
@@ -174,7 +172,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) {
@@ -188,13 +186,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,
       )));
     }
@@ -222,7 +220,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/tests/config_test/config/schema/config_test.schema.yml b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml
index 984026f..33662e6 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,12 +1,11 @@
 # Schema for the configuration files of the Configuration Test module.
 
-config_test.dynamic.*:
+config_test_dynamic:
   type: mapping
-  label: 'Config test entity'
   mapping:
     id:
       type: string
-      label: 'Machine name'
+      label: 'ID'
     label:
       type: label
       label: 'Label'
@@ -15,12 +14,35 @@ config_test.dynamic.*:
       label: 'Weight'
     style:
       type: string
-      label: 'Image style'
+      label: 'style'
+    test_dependencies:
+      type: config_dependencies
+      label: 'Configuration dependencies'
+    status:
+      type: boolean
+      label: 'Status'
+    uuid:
+      type: string
+      label: 'UUID'
+    langcode:
+      type: string
+      label: 'Default language'
+    dependencies:
+      type: config_dependencies
+      label: 'Configuration dependencies'
     protected_property:
       type: string
       label: 'Protected property'
 
-config_test_dynamic:
+config_test.dynamic.*:
+  type: config_test_dynamic
+  label: 'Config test dynamic settings'
+
+config_test.dynamic.*.*:
+  type: config_test_dynamic
+  label: 'Config test dynamic settings'
+
+config_test.query.*:
   type: mapping
   mapping:
     id:
@@ -32,29 +54,23 @@ config_test_dynamic:
     label:
       type: label
       label: 'Label'
-    weight:
+    array:
+      type: sequence
+      label: 'Array'
+      sequence:
+        - type: string
+    number:
       type: integer
-      label: 'Weight'
-    style:
-      type: string
-      label: 'style'
+      label: 'number'
     status:
       type: boolean
       label: 'Status'
     langcode:
       type: string
       label: 'Default language'
-    protected_property:
-      type: string
-      label: 'Protected property'
-
-config_test.dynamic.*:
-  type: config_test_dynamic
-  label: 'Config test dynamic settings'
-
-config_test.dynamic.*.*:
-  type: config_test_dynamic
-  label: 'Config test dynamic settings'
+    dependencies:
+      type: config_dependencies
+      label: 'Configuration dependencies'
 
 config_test.types:
   type: mapping
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
index 07ec50a..b5f2dea 100644
--- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/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.
@@ -86,20 +86,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().
    */
   public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
diff --git a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php
index a3d6ece..cfbc471 100644
--- a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php
+++ b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php
@@ -70,21 +70,6 @@ class DateFormat extends ConfigEntityBase implements DateFormatInterface {
   /**
    * {@inheritdoc}
    */
-  public function toArray() {
-    $properties = parent::toArray();
-    $names = array(
-      'locked',
-      'pattern',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getPattern($type = DrupalDateTime::PHP) {
     return isset($this->pattern[$type]) ? $this->pattern[$type] : '';
   }
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 3c52f73..0b1485f 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -86,6 +86,13 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
   protected $cacheBackend;
 
   /**
+   * The mocked typed config manager.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $typedConfigManager;
+
+  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
@@ -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,6 +441,18 @@ 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);
+    $this->assertEquals(array('id' => $this->entity->id(), 'dependencies' => array()), $properties);
+  }
+
+  /**
+   * @covers ::toArray
+   */
+  public function testToArrayFallback() {
     $properties = $this->entity->toArray();
     $this->assertInternalType('array', $properties);
     $class_info = new \ReflectionClass($this->entity);
@@ -439,6 +461,7 @@ public function testToArray() {
       $this->assertArrayHasKey($name, $properties);
       $this->assertSame($this->entity->get($name), $properties[$name]);
     }
+    $this->assertArrayNotHasKey('dependencies', $properties);
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 37019f5..6eee404 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -98,6 +98,13 @@ class ConfigEntityStorageTest extends UnitTestCase {
   protected $cacheBackend;
 
   /**
+   * The mocked typed config manager.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $typedConfigManager;
+
+  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
@@ -167,8 +174,11 @@ protected 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('config.typed', $this->typedConfigManager);
     $container->set('cache.test', $this->cacheBackend);
     $container->setParameter('cache_bins', array('cache.test' => 'test'));
     \Drupal::setContainer($container);
@@ -242,7 +252,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 +311,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 +371,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');
