diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
index 2a87d03fa9a872b04e39acfa797de524272e620b..e7209f1f33fe375a035a68877436812219fba2b8 100644
--- a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
+++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
@@ -351,13 +351,17 @@ abstract protected function allowedValuesDescription();
   public static function validateAllowedValues($element, FormStateInterface $form_state) {
     $items = array_filter(array_map(function ($item) use ($element) {
       $current_element = $element['table'][$item];
-      if ($current_element['item']['key']['#value'] !== NULL && $current_element['item']['label']['#value']) {
-        return $current_element['item']['key']['#value'] . '|' . $current_element['item']['label']['#value'];
-      }
-      elseif ($current_element['item']['key']['#value']) {
+      $key_has_input = isset($current_element['item']['key']['#value']) && $current_element['item']['key']['#value'] !== '';
+      $label_has_input = isset($current_element['item']['label']['#value']) && $current_element['item']['label']['#value'] !== '';
+      if ($key_has_input) {
+        if ($label_has_input) {
+          return $current_element['item']['key']['#value'] . '|' . $current_element['item']['label']['#value'];
+        }
+
         return $current_element['item']['key']['#value'];
       }
-      elseif ($current_element['item']['label']['#value']) {
+
+      if ($label_has_input) {
         return $current_element['item']['label']['#value'];
       }
 
diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php
index c31f1bc13768c31a35a99f3aa705ee9e493b7fca..4e6ce2b9dcf205d9a81b790ab4b19e7e2844b08f 100644
--- a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php
+++ b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php
@@ -93,6 +93,9 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state
     // Improve user experience by using an automatically generated machine name.
     foreach (Element::children($element['allowed_values']['table']) as $delta => $row) {
       $element['allowed_values']['table'][$delta]['item']['key']['#type'] = 'machine_name';
+      // ListItemBase::storageSettingsForm() will set the default value to an
+      // integer if the key is a decimal integer string, so cast it back here.
+      $element['allowed_values']['table'][$delta]['item']['key']['#default_value'] = (string) $element['allowed_values']['table'][$delta]['item']['key']['#default_value'];
       $element['allowed_values']['table'][$delta]['item']['key']['#machine_name'] = [
         'exists' => [static::class, 'exists'],
       ];
diff --git a/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php b/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php
index fec03135703f1c31c8ea1f3340fcca3cc75ca507..5266f1c950aa993c135c4bf8c2d25336fd76c059 100644
--- a/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php
+++ b/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php
@@ -172,42 +172,45 @@ public function testOptionsAllowedValues($option_type, $options, $is_string_opti
     }
     $page->pressButton('Save');
 
+    $option_labels = array_values($options);
+    $this->assertCount(3, $option_labels);
+
     // Test the order of the option list on node form.
     $this->drupalGet($this->nodeFormPath);
-    $this->assertNodeFormOrder(['- None -', 'First', 'Second', 'Third']);
+    $this->assertNodeFormOrder(['- None -', $option_labels[0], $option_labels[1], $option_labels[2]]);
 
     // Test the order of the option list on admin path.
     $this->drupalGet($this->adminPath);
-    $this->assertOrder(['First', 'Second', 'Third', ''], $is_string_option);
+    $this->assertOrder([$option_labels[0], $option_labels[1], $option_labels[2], ''], $is_string_option);
     $drag_handle = $page->find('css', '[data-drupal-selector="edit-field-storage-subform-settings-allowed-values-table-0"] .tabledrag-handle');
     $target = $page->find('css', '[data-drupal-selector="edit-field-storage-subform-settings-allowed-values-table-2"]');
 
     // Change the order the items appear.
     $drag_handle->dragTo($target);
-    $this->assertOrder(['Second', 'Third', 'First', ''], $is_string_option);
+    $this->assertOrder([$option_labels[1], $option_labels[2], $option_labels[0], ''], $is_string_option);
     $page->pressButton('Save');
 
     $this->drupalGet($this->nodeFormPath);
-    $this->assertNodeFormOrder(['- None -', 'Second', 'Third', 'First']);
+    $this->assertNodeFormOrder(['- None -', $option_labels[1], $option_labels[2], $option_labels[0]]);
 
     $this->drupalGet($this->adminPath);
 
     // Confirm the change in order was saved.
-    $this->assertOrder(['Second', 'Third', 'First', ''], $is_string_option);
+    $this->assertOrder([$option_labels[1], $option_labels[2], $option_labels[0], ''], $is_string_option);
 
     // Delete an item.
     $page->pressButton('remove_row_button__1');
     $this->assertSession()->assertWaitOnAjaxRequest();
-    $this->assertOrder(['Second', 'First', ''], $is_string_option);
+    $this->assertOrder([$option_labels[1], $option_labels[0], ''], $is_string_option);
     $page->pressButton('Save');
 
     $this->drupalGet($this->nodeFormPath);
-    $this->assertNodeFormOrder(['- None -', 'Second', 'First']);
+    $this->assertNodeFormOrder(['- None -', $option_labels[1], $option_labels[0]]);
 
     $this->drupalGet($this->adminPath);
 
     // Confirm the item removal was saved.
-    $this->assertOrder(['Second', 'First', ''], $is_string_option);
+    $this->assertOrder([$option_labels[1], $option_labels[0], ''], $is_string_option);
   }
 
   /**
@@ -316,6 +319,12 @@ public static function providerTestOptionsAllowedValues() {
         ['first' => 'First', 'second' => 'Second', 'third' => 'Third'],
         TRUE,
       ],
+      // Example with empty key and label values like string '0'.
+      'List string with 0 value' => [
+        'list_string',
+        ['0' => '0', '1' => '1', '2' => '2'],
+        TRUE,
+      ],
     ];
     // Test adding options for each option field type using several possible
     // methods that could be used for navigating the options list: