diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index 0128c66..79db0c2 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -208,9 +208,7 @@ public function save($has_trusted_data = FALSE) {
       if ($this->typedConfigManager->hasConfigSchema($this->name)) {
         // Ensure that the schema wrapper has the latest data.
         $this->schemaWrapper = NULL;
-        foreach ($this->data as $key => $value) {
-          $this->data[$key] = $this->castValue($key, $value);
-        }
+        $this->data = $this->castValue(NULL, $this->data);
       }
       else {
         foreach ($this->data as $key => $value) {
diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php
index 40a25ef..a32087a 100644
--- a/core/lib/Drupal/Core/Config/StorableConfigBase.php
+++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Core\Config\Schema\Ignore;
+use Drupal\Core\Config\Schema\Mapping;
 use Drupal\Core\TypedData\PrimitiveInterface;
 use Drupal\Core\TypedData\Type\FloatInterface;
 use Drupal\Core\TypedData\Type\IntegerInterface;
@@ -164,8 +165,9 @@ protected function validateValue($key, $value) {
   /**
    * Casts the value to correct data type using the configuration schema.
    *
-   * @param string $key
-   *   A string that maps to a key within the configuration data.
+   * @param string|null $key
+   *   A string that maps to a key within the configuration data. If NULL the
+   *   top level mapping will be processed.
    * @param string $value
    *   Value to associate with the key.
    *
@@ -176,7 +178,11 @@ protected function validateValue($key, $value) {
    *   If the value is unsupported in configuration.
    */
   protected function castValue($key, $value) {
-    $element = $this->getSchemaWrapper()->get($key);
+    $element = $this->getSchemaWrapper();
+    if ($key !== NULL) {
+      $element = $element->get($key);
+    }
+
     // Do not cast value if it is unknown or defined to be ignored.
     if ($element && ($element instanceof Undefined || $element instanceof Ignore)) {
       // Do validate the value (may throw UnsupportedDataTypeConfigException)
@@ -208,7 +214,17 @@ protected function castValue($key, $value) {
       }
       // Recurse into any nested keys.
       foreach ($value as $nested_value_key => $nested_value) {
-        $value[$nested_value_key] = $this->castValue($key . '.' . $nested_value_key, $nested_value);
+        $lookup_key = $key ? $key . '.' . $nested_value_key : $nested_value_key;
+        $value[$nested_value_key] = $this->castValue($lookup_key, $nested_value);
+      }
+
+      // Only sort maps when we have more than 1 element to sort.
+      if ($element instanceof Mapping && count($value) > 1) {
+        $mapping = $element->getDataDefinition()['mapping'];
+        // Only sort the keys in $value.
+        $mapping = array_intersect_key($mapping, $value);
+        // Sort the array in $value using the mapping definition.
+        $value = array_replace($mapping, $value);
       }
     }
     return $value;
diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml
index e0232cf..702390e 100644
--- a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml
+++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.default.yml
@@ -12,9 +12,9 @@ content:
     type: timestamp_ago
     weight: 1
     region: content
+    label: inline
     settings: {  }
     third_party_settings: {  }
-    label: inline
   description:
     weight: 3
     region: content
@@ -31,8 +31,8 @@ content:
     type: uri_link
     weight: 4
     region: content
+    label: inline
     settings: {  }
     third_party_settings: {  }
-    label: inline
 hidden:
   more_link: true
diff --git a/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php b/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php
index d31c92c..20c56b9 100644
--- a/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php
+++ b/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php
@@ -94,8 +94,8 @@ protected function createTests() {
       'settings' => array(
         'id' => 'test_html',
         'label' => '',
-        'provider' => 'block_test',
         'label_display' => BlockPluginInterface::BLOCK_LABEL_VISIBLE,
+        'provider' => 'block_test',
       ),
       'visibility' => array(),
     );
diff --git a/core/modules/book/config/optional/core.entity_form_display.node.book.default.yml b/core/modules/book/config/optional/core.entity_form_display.node.book.default.yml
index 58aba45..b90eb49 100644
--- a/core/modules/book/config/optional/core.entity_form_display.node.book.default.yml
+++ b/core/modules/book/config/optional/core.entity_form_display.node.book.default.yml
@@ -28,17 +28,17 @@ content:
     third_party_settings: {  }
   promote:
     type: boolean_checkbox
-    settings:
-      display_label: true
     weight: 15
     region: content
+    settings:
+      display_label: true
     third_party_settings: {  }
   sticky:
     type: boolean_checkbox
-    settings:
-      display_label: true
     weight: 16
     region: content
+    settings:
+      display_label: true
     third_party_settings: {  }
   title:
     type: string_textfield
diff --git a/core/modules/book/config/optional/core.entity_view_display.node.book.default.yml b/core/modules/book/config/optional/core.entity_view_display.node.book.default.yml
index d6ef64d..f39e28a 100644
--- a/core/modules/book/config/optional/core.entity_view_display.node.book.default.yml
+++ b/core/modules/book/config/optional/core.entity_view_display.node.book.default.yml
@@ -13,10 +13,10 @@ bundle: book
 mode: default
 content:
   body:
-    label: hidden
     type: text_default
     weight: 100
     region: content
+    label: hidden
     settings: {  }
     third_party_settings: {  }
   links:
diff --git a/core/modules/book/config/optional/core.entity_view_display.node.book.teaser.yml b/core/modules/book/config/optional/core.entity_view_display.node.book.teaser.yml
index 77a62c3..619ca71 100644
--- a/core/modules/book/config/optional/core.entity_view_display.node.book.teaser.yml
+++ b/core/modules/book/config/optional/core.entity_view_display.node.book.teaser.yml
@@ -14,10 +14,10 @@ bundle: book
 mode: teaser
 content:
   body:
-    label: hidden
     type: text_summary_or_trimmed
     weight: 100
     region: content
+    label: hidden
     settings:
       trim_length: 600
     third_party_settings: {  }
diff --git a/core/modules/book/config/optional/core.entity_view_mode.node.print.yml b/core/modules/book/config/optional/core.entity_view_mode.node.print.yml
index d615b03..d695ac5 100644
--- a/core/modules/book/config/optional/core.entity_view_mode.node.print.yml
+++ b/core/modules/book/config/optional/core.entity_view_mode.node.print.yml
@@ -1,11 +1,11 @@
 langcode: en
 status: false
 dependencies:
+  module:
+    - node
   enforced:
     module:
       - book
-  module:
-    - node
 id: node.print
 label: Print
 targetEntityType: node
diff --git a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
index c10e268..e192a30 100644
--- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
+++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
@@ -297,3 +297,18 @@ test.double_brackets.breed:
   mapping:
     breed:
       type: string
+
+config_schema_test.schema_mapping_sort:
+  type: config_object
+  mapping:
+    bar:
+      type: string
+    foo:
+      type: string
+    map:
+      type: mapping
+      mapping:
+        sub_foo:
+          type: string
+        sub_bar:
+          type: string
diff --git a/core/modules/content_moderation/config/install/workflows.workflow.editorial.yml b/core/modules/content_moderation/config/install/workflows.workflow.editorial.yml
index d8daa51..96d7a83 100644
--- a/core/modules/content_moderation/config/install/workflows.workflow.editorial.yml
+++ b/core/modules/content_moderation/config/install/workflows.workflow.editorial.yml
@@ -5,6 +5,19 @@ dependencies:
     - content_moderation
 id: editorial
 label: 'Editorial workflow'
+type: content_moderation
+type_settings:
+  states:
+    archived:
+      published: false
+      default_revision: true
+    draft:
+      published: false
+      default_revision: false
+    published:
+      published: true
+      default_revision: true
+  entity_types: {  }
 states:
   archived:
     label: Archived
@@ -48,16 +61,3 @@ transitions:
       - published
     to: published
     weight: 1
-type: content_moderation
-type_settings:
-  states:
-    archived:
-      published: false
-      default_revision: true
-    draft:
-      published: false
-      default_revision: false
-    published:
-      published: true
-      default_revision: true
-  entity_types: {  }
diff --git a/core/modules/forum/config/optional/core.entity_form_display.node.forum.default.yml b/core/modules/forum/config/optional/core.entity_form_display.node.forum.default.yml
index 6773d32..8751d50 100644
--- a/core/modules/forum/config/optional/core.entity_form_display.node.forum.default.yml
+++ b/core/modules/forum/config/optional/core.entity_form_display.node.forum.default.yml
@@ -37,17 +37,17 @@ content:
     third_party_settings: {  }
   promote:
     type: boolean_checkbox
-    settings:
-      display_label: true
     weight: 15
     region: content
+    settings:
+      display_label: true
     third_party_settings: {  }
   sticky:
     type: boolean_checkbox
-    settings:
-      display_label: true
     weight: 16
     region: content
+    settings:
+      display_label: true
     third_party_settings: {  }
   taxonomy_forums:
     type: options_select
diff --git a/core/modules/forum/config/optional/core.entity_view_display.comment.comment_forum.default.yml b/core/modules/forum/config/optional/core.entity_view_display.comment.comment_forum.default.yml
index befeba8..72ef82b 100644
--- a/core/modules/forum/config/optional/core.entity_view_display.comment.comment_forum.default.yml
+++ b/core/modules/forum/config/optional/core.entity_view_display.comment.comment_forum.default.yml
@@ -12,10 +12,10 @@ bundle: comment_forum
 mode: default
 content:
   comment_body:
-    label: hidden
     type: text_default
     weight: 0
     region: content
+    label: hidden
     settings: {  }
     third_party_settings: {  }
   links:
diff --git a/core/modules/forum/config/optional/core.entity_view_display.node.forum.default.yml b/core/modules/forum/config/optional/core.entity_view_display.node.forum.default.yml
index f3e8c5c..2570925 100644
--- a/core/modules/forum/config/optional/core.entity_view_display.node.forum.default.yml
+++ b/core/modules/forum/config/optional/core.entity_view_display.node.forum.default.yml
@@ -17,17 +17,17 @@ bundle: forum
 mode: default
 content:
   body:
-    label: hidden
     type: text_default
     weight: 0
     region: content
+    label: hidden
     settings: {  }
     third_party_settings: {  }
   comment_forum:
-    label: hidden
     type: comment_default
     weight: 20
     region: content
+    label: hidden
     settings:
       view_mode: default
       pager_id: 0
diff --git a/core/modules/forum/config/optional/core.entity_view_display.node.forum.teaser.yml b/core/modules/forum/config/optional/core.entity_view_display.node.forum.teaser.yml
index 7b174f4..eb1c3d3 100644
--- a/core/modules/forum/config/optional/core.entity_view_display.node.forum.teaser.yml
+++ b/core/modules/forum/config/optional/core.entity_view_display.node.forum.teaser.yml
@@ -16,10 +16,10 @@ bundle: forum
 mode: teaser
 content:
   body:
-    label: hidden
     type: text_summary_or_trimmed
     weight: 100
     region: content
+    label: hidden
     settings:
       trim_length: 600
     third_party_settings: {  }
diff --git a/core/modules/forum/config/optional/core.entity_view_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/optional/core.entity_view_display.taxonomy_term.forums.default.yml
index b326039..aecec5b 100644
--- a/core/modules/forum/config/optional/core.entity_view_display.taxonomy_term.forums.default.yml
+++ b/core/modules/forum/config/optional/core.entity_view_display.taxonomy_term.forums.default.yml
@@ -15,8 +15,8 @@ content:
     type: text_default
     weight: 0
     region: content
+    label: above
     settings: {  }
     third_party_settings: {  }
-    label: above
 hidden:
   forum_container: true
diff --git a/core/modules/forum/config/optional/field.field.node.forum.comment_forum.yml b/core/modules/forum/config/optional/field.field.node.forum.comment_forum.yml
index 8812273..e5edd7e 100644
--- a/core/modules/forum/config/optional/field.field.node.forum.comment_forum.yml
+++ b/core/modules/forum/config/optional/field.field.node.forum.comment_forum.yml
@@ -18,15 +18,15 @@ default_value:
   -
     status: 2
     cid: 0
-    last_comment_name: null
     last_comment_timestamp: 0
+    last_comment_name: null
     last_comment_uid: 0
     comment_count: 0
 default_value_callback: ''
 settings:
   default_mode: 0
   per_page: 50
-  form_location: true
   anonymous: 0
+  form_location: true
   preview: 1
 field_type: comment
diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml
index 0006ad7..4276644 100644
--- a/core/modules/image/config/schema/image.schema.yml
+++ b/core/modules/image/config/schema/image.schema.yml
@@ -14,14 +14,14 @@ image.style.*:
       sequence:
         type: mapping
         mapping:
+          uuid:
+            type: string
           id:
             type: string
-          data:
-            type: image.effect.[%parent.id]
           weight:
             type: integer
-          uuid:
-            type: string
+          data:
+            type: image.effect.[%parent.id]
 
 image.effect.*:
   type: mapping
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php
index 8a39d64..7cf1fca 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php
@@ -396,6 +396,24 @@ public function testConfigSaveWithSchema() {
   }
 
   /**
+   * Test configuration value data type enforcement using schemas.
+   */
+  public function testConfigSaveMappingSort() {
+    // Top level map sorting.
+    $data = [
+      'foo' => '1',
+      'bar' => '2',
+    ];
+    // Save config which has a schema that enforces types.
+    $this->config('config_schema_test.schema_mapping_sort')
+      ->setData($data)
+      ->save();
+    $this->assertSame(['bar' => '2', 'foo' => '1'], $this->config('config_schema_test.schema_mapping_sort')->get());
+    $this->config('config_schema_test.schema_mapping_sort')->set('map', ['sub_bar' => '2', 'sub_foo' => '1'])->save();
+    $this->assertSame(['sub_foo' => '1', 'sub_bar' => '2'], $this->config('config_schema_test.schema_mapping_sort')->get('map'));
+  }
+
+  /**
    * Tests fallback to a greedy wildcard.
    */
   function testSchemaFallback() {
