diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index c3e18e1b9dec3460f8847ebffe1215109b8e430b..88f48c25593e2c67ad087620be707cfe1ed0d8b3 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2013,58 +2013,6 @@ function drupal_get_hash_salt() {
   return !empty($drupal_hash_salt) ? $drupal_hash_salt : '';
 }
 
-/**
- * Merges multiple arrays, recursively, and returns the merged array.
- *
- * This function is similar to PHP's array_merge_recursive() function, but it
- * handles non-array values differently. When merging values that are not both
- * arrays, the latter value replaces the former rather than merging with it.
- *
- * Example:
- * @code
- * $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => t('X'), 'class' => array('a', 'b')));
- * $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => t('Y'), 'class' => array('c', 'd')));
- *
- * // This results in array('fragment' => array('x', 'y'), 'attributes' => array('title' => array(t('X'), t('Y')), 'class' => array('a', 'b', 'c', 'd'))).
- * $incorrect = array_merge_recursive($link_options_1, $link_options_2);
- *
- * // This results in array('fragment' => 'y', 'attributes' => array('title' => t('Y'), 'class' => array('a', 'b', 'c', 'd'))).
- * $correct = drupal_array_merge_deep($link_options_1, $link_options_2);
- * @endcode
- *
- * @param ...
- *   Arrays to merge.
- *
- * @return
- *   The merged array.
- *
- * @see drupal_array_merge_deep_array()
- */
-function drupal_array_merge_deep() {
-  return drupal_array_merge_deep_array(func_get_args());
-}
-
-/**
- * Merges multiple arrays, recursively, and returns the merged array.
- *
- * This function is equivalent to drupal_array_merge_deep(), except the
- * input arrays are passed as a single array parameter rather than a variable
- * parameter list.
- *
- * The following are equivalent:
- * - drupal_array_merge_deep($a, $b);
- * - drupal_array_merge_deep_array(array($a, $b));
- *
- * The following are also equivalent:
- * - call_user_func_array('drupal_array_merge_deep', $arrays_to_merge);
- * - drupal_array_merge_deep_array($arrays_to_merge);
- *
- * @see drupal_array_merge_deep()
- */
-function drupal_array_merge_deep_array($arrays) {
-  return NestedArray::mergeDeepArray($arrays);
-}
-
 /**
  * Generates a default anonymous $user object.
  *
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 12537dfc4b8f3538946bd8f0dea95002ef202efa..b13c3bc3f8ecad7dae1ff421ff47a21c07f42ec8 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3954,7 +3954,7 @@ function drupal_pre_render_scripts($elements) {
         switch ($item['type']) {
           case 'setting':
             $element['#value_prefix'] = $embed_prefix;
-            $element['#value'] = 'var drupalSettings = ' . drupal_json_encode(drupal_array_merge_deep_array($item['data'])) . ";";
+            $element['#value'] = 'var drupalSettings = ' . drupal_json_encode(NestedArray::mergeDeepArray($item['data'])) . ";";
             $element['#value_suffix'] = $embed_suffix;
             break;
 
@@ -6087,225 +6087,6 @@ function element_set_attributes(array &$element, array $map) {
   }
 }
 
-/**
- * Retrieves a value from a nested array with variable depth.
- *
- * This helper function should be used when the depth of the array element being
- * retrieved may vary (that is, the number of parent keys is variable). It is
- * primarily used for form structures and renderable arrays.
- *
- * Without this helper function the only way to get a nested array value with
- * variable depth in one line would be using eval(), which should be avoided:
- * @code
- * // Do not do this! Avoid eval().
- * // May also throw a PHP notice, if the variable array keys do not exist.
- * eval('$value = $array[\'' . implode("']['", $parents) . "'];");
- * @endcode
- *
- * Instead, use this helper function:
- * @code
- * $value = drupal_array_get_nested_value($form, $parents);
- * @endcode
- *
- * The return value will be NULL, regardless of whether the actual value is NULL
- * or whether the requested key does not exist. If it is required to know
- * whether the nested array key actually exists, pass a third argument that is
- * altered by reference:
- * @code
- * $key_exists = NULL;
- * $value = drupal_array_get_nested_value($form, $parents, $key_exists);
- * if ($key_exists) {
- *   // ... do something with $value ...
- * }
- * @endcode
- *
- * However if the number of array parent keys is static, the value should always
- * be retrieved directly rather than calling this function. For instance:
- * @code
- * $value = $form['signature_settings']['signature'];
- * @endcode
- *
- * @param $array
- *   The array from which to get the value.
- * @param $parents
- *   An array of parent keys of the value, starting with the outermost key.
- * @param $key_exists
- *   (optional) If given, an already defined variable that is altered by
- *   reference.
- *
- * @return
- *   The requested nested value. Possibly NULL if the value is NULL or not all
- *   nested parent keys exist. $key_exists is altered by reference and is a
- *   Boolean that indicates whether all nested parent keys exist (TRUE) or not
- *   (FALSE). This allows to distinguish between the two possibilities when NULL
- *   is returned.
- *
- * @see drupal_array_set_nested_value()
- * @see drupal_array_unset_nested_value()
- */
-function &drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) {
-  return NestedArray::getValue($array, $parents, $key_exists);
-}
-
-/**
- * Sets a value in a nested array with variable depth.
- *
- * This helper function should be used when the depth of the array element you
- * are changing may vary (that is, the number of parent keys is variable). It
- * is primarily used for form structures and renderable arrays.
- *
- * Example:
- * @code
- * // Assume you have a 'signature' element somewhere in a form. It might be:
- * $form['signature_settings']['signature'] = array(
- *   '#type' => 'text_format',
- *   '#title' => t('Signature'),
- * );
- * // Or, it might be further nested:
- * $form['signature_settings']['user']['signature'] = array(
- *   '#type' => 'text_format',
- *   '#title' => t('Signature'),
- * );
- * @endcode
- *
- * To deal with the situation, the code needs to figure out the route to the
- * element, given an array of parents that is either
- * @code array('signature_settings', 'signature') @endcode in the first case or
- * @code array('signature_settings', 'user', 'signature') @endcode in the second
- * case.
- *
- * Without this helper function the only way to set the signature element in one
- * line would be using eval(), which should be avoided:
- * @code
- * // Do not do this! Avoid eval().
- * eval('$form[\'' . implode("']['", $parents) . '\'] = $element;');
- * @endcode
- *
- * Instead, use this helper function:
- * @code
- * drupal_array_set_nested_value($form, $parents, $element);
- * @endcode
- *
- * However if the number of array parent keys is static, the value should always
- * be set directly rather than calling this function. For instance, for the
- * first example we could just do:
- * @code
- * $form['signature_settings']['signature'] = $element;
- * @endcode
- *
- * @param $array
- *   A reference to the array to modify.
- * @param $parents
- *   An array of parent keys, starting with the outermost key.
- * @param $value
- *   The value to set.
- * @param $force
- *   (Optional) If TRUE, the value is forced into the structure even if it
- *   requires the deletion of an already existing non-array parent value. If
- *   FALSE, PHP throws an error if trying to add into a value that is not an
- *   array. Defaults to FALSE.
- *
- * @see drupal_array_unset_nested_value()
- * @see drupal_array_get_nested_value()
- */
-function drupal_array_set_nested_value(array &$array, array $parents, $value, $force = FALSE) {
-  NestedArray::setValue($array, $parents, $value, $force);
-}
-
-/**
- * Unsets a value in a nested array with variable depth.
- *
- * This helper function should be used when the depth of the array element you
- * are changing may vary (that is, the number of parent keys is variable). It
- * is primarily used for form structures and renderable arrays.
- *
- * Example:
- * @code
- * // Assume you have a 'signature' element somewhere in a form. It might be:
- * $form['signature_settings']['signature'] = array(
- *   '#type' => 'text_format',
- *   '#title' => t('Signature'),
- * );
- * // Or, it might be further nested:
- * $form['signature_settings']['user']['signature'] = array(
- *   '#type' => 'text_format',
- *   '#title' => t('Signature'),
- * );
- * @endcode
- *
- * To deal with the situation, the code needs to figure out the route to the
- * element, given an array of parents that is either
- * @code array('signature_settings', 'signature') @endcode in the first case or
- * @code array('signature_settings', 'user', 'signature') @endcode in the second
- * case.
- *
- * Without this helper function the only way to unset the signature element in
- * one line would be using eval(), which should be avoided:
- * @code
- * // Do not do this! Avoid eval().
- * eval('unset($form[\'' . implode("']['", $parents) . '\']);');
- * @endcode
- *
- * Instead, use this helper function:
- * @code
- * drupal_array_unset_nested_value($form, $parents, $element);
- * @endcode
- *
- * However if the number of array parent keys is static, the value should always
- * be set directly rather than calling this function. For instance, for the
- * first example we could just do:
- * @code
- * unset($form['signature_settings']['signature']);
- * @endcode
- *
- * @param $array
- *   A reference to the array to modify.
- * @param $parents
- *   An array of parent keys, starting with the outermost key and including the
- *   key to be unset.
- * @param $key_existed
- *   (optional) If given, an already defined variable that is altered by
- *   reference.
- *
- * @see drupal_array_set_nested_value()
- * @see drupal_array_get_nested_value()
- */
-function drupal_array_unset_nested_value(array &$array, array $parents, &$key_existed = NULL) {
-  NestedArray::unsetValue($array, $parents, $key_existed);
-}
-
-/**
- * Determines whether a nested array contains the requested keys.
- *
- * This helper function should be used when the depth of the array element to be
- * checked may vary (that is, the number of parent keys is variable). See
- * drupal_array_set_nested_value() for details. It is primarily used for form
- * structures and renderable arrays.
- *
- * If it is required to also get the value of the checked nested key, use
- * drupal_array_get_nested_value() instead.
- *
- * If the number of array parent keys is static, this helper function is
- * unnecessary and the following code can be used instead:
- * @code
- * $value_exists = isset($form['signature_settings']['signature']);
- * $key_exists = array_key_exists('signature', $form['signature_settings']);
- * @endcode
- *
- * @param $array
- *   The array with the value to check for.
- * @param $parents
- *   An array of parent keys of the value, starting with the outermost key.
- *
- * @return
- *   TRUE if all the parent keys exist, FALSE otherwise.
- *
- * @see drupal_array_get_nested_value()
- */
-function drupal_array_nested_key_exists(array $array, array $parents) {
-  return NestedArray::keyExists($array, $parents);
-}
-
 /**
  * Parses Drupal module and theme .info files.
  *
diff --git a/core/includes/form.inc b/core/includes/form.inc
index f5f5b980664f0dd367efc8a05a98f4932086d53f..b26966f3bf27266f12a454dcf38c67595508419f 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -5,6 +5,7 @@
  * Functions for form and batch generation and processing.
  */
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Utility\Color;
 use Drupal\Core\Template\Attribute;
 
@@ -1160,9 +1161,9 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
       // If the section exists within $form_state['values'], even if the value
       // is NULL, copy it to $values.
       $section_exists = NULL;
-      $value = drupal_array_get_nested_value($form_state['values'], $section, $section_exists);
+      $value = NestedArray::getValue($form_state['values'], $section, $section_exists);
       if ($section_exists) {
-        drupal_array_set_nested_value($values, $section, $value);
+        NestedArray::setValue($values, $section, $value);
       }
     }
     // A button's #value does not require validation, so for convenience we
@@ -1176,8 +1177,8 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
       // dictated by #parents. If it is, copy it to $values, but do not override
       // what may already be in $values.
       $parents = $form_state['triggering_element']['#parents'];
-      if (!drupal_array_nested_key_exists($values, $parents) && drupal_array_get_nested_value($form_state['values'], $parents) === $button_value) {
-        drupal_array_set_nested_value($values, $parents, $button_value);
+      if (!NestedArray::keyExists($values, $parents) && NestedArray::getValue($form_state['values'], $parents) === $button_value) {
+        NestedArray::setValue($values, $parents, $button_value);
       }
 
       // Additionally, form_builder() places the button value in
@@ -2024,7 +2025,7 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
       // Get the input for the current element. NULL values in the input need to
       // be explicitly distinguished from missing input. (see below)
       $input_exists = NULL;
-      $input = drupal_array_get_nested_value($form_state['input'], $element['#parents'], $input_exists);
+      $input = NestedArray::getValue($form_state['input'], $element['#parents'], $input_exists);
       // For browser-submitted forms, the submitted values do not contain values
       // for certain elements (empty multiple select, unchecked checkbox).
       // During initial form processing, we add explicit NULL values for such
@@ -2037,7 +2038,7 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
       if (!$input_exists && !$form_state['rebuild'] && !$form_state['programmed']) {
         // Add the necessary parent keys to $form_state['input'] and sets the
         // element's input value to NULL.
-        drupal_array_set_nested_value($form_state['input'], $element['#parents'], NULL);
+        NestedArray::setValue($form_state['input'], $element['#parents'], NULL);
         $input_exists = TRUE;
       }
       // If we have input for the current element, assign it to the #value
@@ -2096,7 +2097,7 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) {
 
   // Set the element's value in $form_state['values'], but only, if its key
   // does not exist yet (a #value_callback may have already populated it).
-  if (!drupal_array_nested_key_exists($form_state['values'], $element['#parents'])) {
+  if (!NestedArray::keyExists($form_state['values'], $element['#parents'])) {
     form_set_value($element, $element['#value'], $form_state);
   }
 }
@@ -2209,7 +2210,7 @@ function form_state_values_clean(&$form_state) {
     $parents = $button['#parents'];
     $last_parent = array_pop($parents);
     $key_exists = NULL;
-    $values = &drupal_array_get_nested_value($form_state['values'], $parents, $key_exists);
+    $values = &NestedArray::getValue($form_state['values'], $parents, $key_exists);
     if ($key_exists && is_array($values)) {
       unset($values[$last_parent]);
     }
@@ -2550,7 +2551,7 @@ function form_type_token_value($element, $input = FALSE) {
  *   Form state array where the value change should be recorded.
  */
 function form_set_value($element, $value, &$form_state) {
-  drupal_array_set_nested_value($form_state['values'], $element['#parents'], $value, TRUE);
+  NestedArray::setValue($form_state['values'], $element['#parents'], $value, TRUE);
 }
 
 /**
@@ -3637,7 +3638,7 @@ function form_process_machine_name($element, &$form_state) {
   // complete form in $form_state. By reference, because we may need to append
   // a #field_suffix that will hold the live preview.
   $key_exists = NULL;
-  $source = drupal_array_get_nested_value($form_state['complete_form'], $element['#machine_name']['source'], $key_exists);
+  $source = NestedArray::getValue($form_state['complete_form'], $element['#machine_name']['source'], $key_exists);
   if (!$key_exists) {
     return $element;
   }
@@ -3655,7 +3656,7 @@ function form_process_machine_name($element, &$form_state) {
     $source['#field_suffix'] .= ' <small id="' . $suffix_id . '">&nbsp;</small>';
 
     $parents = array_merge($element['#machine_name']['source'], array('#field_suffix'));
-    drupal_array_set_nested_value($form_state['complete_form'], $parents, $source['#field_suffix']);
+    NestedArray::setValue($form_state['complete_form'], $parents, $source['#field_suffix']);
   }
 
   $js_settings = array(
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 386a0020272d84a3c0804cd2341e38f1be235b2a..2620844179b5ae085740b329394eb82d4e72a604 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -5,6 +5,7 @@
  * @{
  */
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\field\FieldUpdateForbiddenException;
 
 /**
@@ -970,7 +971,7 @@ function hook_field_attach_validate($entity_type, $entity, &$errors) {
 function hook_field_attach_submit($entity_type, $entity, $form, &$form_state) {
   // Sample case of an 'Empty the field' checkbox added on the form, allowing
   // a given field to be emptied.
-  $values = drupal_array_get_nested_value($form_state['values'], $form['#parents']);
+  $values = NestedArray::getValue($form_state['values'], $form['#parents']);
   if (!empty($values['empty_field_foo'])) {
     unset($entity->field_foo);
   }
diff --git a/core/modules/field/field.form.inc b/core/modules/field/field.form.inc
index 483c2131f844a7aadeb20e245c4ede608503c095..203a112bec52b2e488c8210f6c0240ada4ebaa3a 100644
--- a/core/modules/field/field.form.inc
+++ b/core/modules/field/field.form.inc
@@ -5,6 +5,8 @@
  * Field forms management.
  */
 
+use Drupal\Component\Utility\NestedArray;
+
 /**
  * Returns HTML for an individual form element.
  *
@@ -124,7 +126,7 @@ function field_add_more_submit($form, &$form_state) {
   $button = $form_state['triggering_element'];
 
   // Go one level up in the form, to the widgets container.
-  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
+  $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
   $field_name = $element['#field_name'];
   $langcode = $element['#language'];
   $parents = $element['#field_parents'];
@@ -149,7 +151,7 @@ function field_add_more_js($form, $form_state) {
   $button = $form_state['triggering_element'];
 
   // Go one level up in the form, to the widgets container.
-  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
+  $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
   $field_name = $element['#field_name'];
   $langcode = $element['#language'];
   $parents = $element['#field_parents'];
@@ -195,7 +197,7 @@ function field_add_more_js($form, $form_state) {
  */
 function field_form_get_state($parents, $field_name, $langcode, &$form_state) {
   $form_state_parents = _field_form_state_parents($parents, $field_name, $langcode);
-  return drupal_array_get_nested_value($form_state, $form_state_parents);
+  return NestedArray::getValue($form_state, $form_state_parents);
 }
 
 /**
@@ -217,7 +219,7 @@ function field_form_get_state($parents, $field_name, $langcode, &$form_state) {
  */
 function field_form_set_state($parents, $field_name, $langcode, &$form_state, $field_state) {
   $form_state_parents = _field_form_state_parents($parents, $field_name, $langcode);
-  drupal_array_set_nested_value($form_state, $form_state_parents, $field_state);
+  NestedArray::setValue($form_state, $form_state_parents, $field_state);
 }
 
 /**
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
index 07806a1f060db9469f246484b85221812dbc449b..de2234972c396e543f2a9ddd72667ce83600de2b 100644
--- a/core/modules/field/field.views.inc
+++ b/core/modules/field/field.views.inc
@@ -7,6 +7,8 @@
  * @ingroup views_module_handlers
  */
 
+use Drupal\Component\Utility\NestedArray;
+
 /**
  * Implements hook_views_data().
  *
@@ -29,7 +31,7 @@ function field_views_data() {
     drupal_alter('field_views_data', $result, $field, $module);
 
     if (is_array($result)) {
-      $data = drupal_array_merge_deep($result, $data);
+      $data = NestedArray::mergeDeep($result, $data);
     }
   }
 
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 1dbe4bba8f16091b0998a653779029b73b13041a..fd434d15eed192c3b3f7a7d6af31d1e4291418ad 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\field\Plugin\Type\Widget;
 
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
 use Drupal\field\FieldInstance;
@@ -319,7 +320,7 @@ public function submit(EntityInterface $entity, $langcode, array &$items, array
     // Extract the values from $form_state['values'].
     $path = array_merge($form['#parents'], array($field_name, $langcode));
     $key_exists = NULL;
-    $values = drupal_array_get_nested_value($form_state['values'], $path, $key_exists);
+    $values = NestedArray::getValue($form_state['values'], $path, $key_exists);
 
     if ($key_exists) {
       // Remove the 'value' of the 'add more' button.
@@ -371,7 +372,7 @@ public function flagErrors(EntityInterface $entity, $langcode, array $items, arr
 
     if (!empty($field_state['errors'])) {
       // Locate the correct element in the the form.
-      $element = drupal_array_get_nested_value($form_state['complete_form'], $field_state['array_parents']);
+      $element = NestedArray::getValue($form_state['complete_form'], $field_state['array_parents']);
 
       // Only set errors if the element is accessible.
       if (!isset($element['#access']) || $element['#access']) {
diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/widget/LegacyWidget.php b/core/modules/field/lib/Drupal/field/Plugin/field/widget/LegacyWidget.php
index 166bd871a865f78082f48e21764a2b6902b640bc..ee66f3fb146d9b7d070c02dd6ef6e9a708995bf3 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/field/widget/LegacyWidget.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/field/widget/LegacyWidget.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field\Plugin\field\widget;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Entity\EntityInterface;
@@ -73,7 +74,7 @@ public function flagErrors(EntityInterface $entity, $langcode, array $items, arr
 
     if (!empty($field_state['errors'])) {
       // Locate the correct element in the form.
-      $element = drupal_array_get_nested_value($form_state['complete_form'], $field_state['array_parents']);
+      $element = NestedArray::getValue($form_state['complete_form'], $field_state['array_parents']);
       // Only set errors if the element is accessible.
       if (!isset($element['#access']) || $element['#access']) {
         $definition = $this->getDefinition();
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index a43849d4c3076ff6e1914fc551c7251ab8141c44..6c696c3e1483e01ccace78f90f31c97d9568aff1 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -5,6 +5,8 @@
  * Field module functionality for the File module.
  */
 
+use Drupal\Component\Utility\NestedArray;
+
 /**
  * Implements hook_field_info().
  */
@@ -442,7 +444,7 @@ function file_field_widget_process($element, &$form_state, $form) {
   if ($field['cardinality'] != 1) {
     $parents = array_slice($element['#array_parents'], 0, -1);
     $new_path = 'file/ajax/' . implode('/', $parents) . '/' . $form['form_build_id']['#value'];
-    $field_element = drupal_array_get_nested_value($form, $parents);
+    $field_element = NestedArray::getValue($form, $parents);
     $new_wrapper = $field_element['#id'] . '-ajax-wrapper';
     foreach (element_children($element) as $key) {
       if (isset($element[$key]['#ajax'])) {
@@ -546,17 +548,17 @@ function file_field_widget_submit($form, &$form_state) {
   // have #default_value set appropriately for the current state of the field,
   // so nothing is lost in doing this.
   $parents = array_slice($form_state['triggering_element']['#parents'], 0, -2);
-  drupal_array_set_nested_value($form_state['input'], $parents, NULL);
+  NestedArray::setValue($form_state['input'], $parents, NULL);
 
   $button = $form_state['triggering_element'];
 
   // Go one level up in the form, to the widgets container.
-  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
+  $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
   $field_name = $element['#field_name'];
   $langcode = $element['#language'];
   $parents = $element['#field_parents'];
 
-  $submitted_values = drupal_array_get_nested_value($form_state['values'], array_slice($button['#array_parents'], 0, -2));
+  $submitted_values = NestedArray::getValue($form_state['values'], array_slice($button['#array_parents'], 0, -2));
   foreach ($submitted_values as $delta => $submitted_value) {
     if (!$submitted_value['fid']) {
       unset($submitted_values[$delta]);
@@ -567,7 +569,7 @@ function file_field_widget_submit($form, &$form_state) {
   $submitted_values = array_values($submitted_values);
 
   // Update form_state values.
-  drupal_array_set_nested_value($form_state['values'], array_slice($button['#array_parents'], 0, -2), $submitted_values);
+  NestedArray::setValue($form_state['values'], array_slice($button['#array_parents'], 0, -2), $submitted_values);
 
   // Update items.
   $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index fd2b269ad33b907932de300d90d395bc0923e98f..193f442f5534dc19ecd44dff8ca1f55885ae9716 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\file\Plugin\Core\Entity\File;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Template\Attribute;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Drupal\file\FileUsage\DatabaseFileUsageBackend;
@@ -1095,7 +1096,7 @@ function file_managed_file_submit($form, &$form_state) {
   // and set $element to the managed_file element that contains that button.
   $parents = $form_state['triggering_element']['#array_parents'];
   $button_key = array_pop($parents);
-  $element = drupal_array_get_nested_value($form, $parents);
+  $element = NestedArray::getValue($form, $parents);
 
   // No action is needed here for the upload button, because all file uploads on
   // the form are processed by file_managed_file_value() regardless of which
@@ -1117,7 +1118,7 @@ function file_managed_file_submit($form, &$form_state) {
     // has correct information during the rebuild.
     $values_element = $element['#extended'] ? $element['fid'] : $element;
     form_set_value($values_element, NULL, $form_state);
-    drupal_array_set_nested_value($form_state['input'], $values_element['#parents'], NULL);
+    NestedArray::setValue($form_state['input'], $values_element['#parents'], NULL);
   }
 
   // Set the form to rebuild so that $form is correctly updated in response to
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index ab5f8d5027405dcad18e7a472e6678ef74602a91..f739f66654b74cd08066b04661345fe94d5d6e7d 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -5,6 +5,8 @@
  * Implement an image field, based on the file module's file field.
  */
 
+use Drupal\Component\Utility\NestedArray;
+
 /**
  * Implements hook_field_info().
  */
@@ -384,7 +386,7 @@ function _image_field_required_fields_validate($element, &$form_state) {
     // If the image is not there, we do not check for empty values.
     $parents = $element['#parents'];
     $field = array_pop($parents);
-    $image_field = drupal_array_get_nested_value($form_state['input'], $parents);
+    $image_field = NestedArray::getValue($form_state['input'], $parents);
     // We check for the array key, so that it can be NULL (like if the user
     // submits the form without using the "upload" button).
     if (!array_key_exists($field, $image_field)) {
diff --git a/core/modules/options/options.module b/core/modules/options/options.module
index e958510537e44042a51702018899c5244e6021ce..d81896627b4ba8344233cf464f317b81a34f83e4 100644
--- a/core/modules/options/options.module
+++ b/core/modules/options/options.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\field\FieldUpdateForbiddenException;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\Query\QueryFactory;
 
 /**
@@ -215,8 +216,8 @@ function options_field_settings_form_validate_allowed_values($element, &$form_st
 * Form element #value_callback: assembles the allowed values for 'boolean' fields.
 */
 function options_field_settings_form_value_boolean_allowed_values($element, $input, $form_state) {
-  $on = drupal_array_get_nested_value($form_state['input'], $element['#on_parents']);
-  $off = drupal_array_get_nested_value($form_state['input'], $element['#off_parents']);
+  $on = NestedArray::getValue($form_state['input'], $element['#on_parents']);
+  $off = NestedArray::getValue($form_state['input'], $element['#off_parents']);
   return array($off, $on);
 }
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 2533fabd6e8714fcb0218ffd4dab62193363aa06..6e41540fa0eab45dbebad9ab0a456243da9280ed 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\simpletest;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\ConnectionNotDefinedException;
@@ -1369,7 +1370,7 @@ protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path
       foreach ($return as $command) {
         switch ($command['command']) {
           case 'settings':
-            $drupal_settings = drupal_array_merge_deep($drupal_settings, $command['settings']);
+            $drupal_settings = NestedArray::mergeDeep($drupal_settings, $command['settings']);
             break;
 
           case 'insert':
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/MiscUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/MiscUnitTest.php
index 88b9ebb9252cce3eef3aa249d7dc24b5353b08c4..f94c419f0f2fd1307388644ebfd80c541b3d17a9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/MiscUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/MiscUnitTest.php
@@ -22,17 +22,6 @@ public static function getInfo() {
     );
   }
 
-  /**
-   * Tests miscellaneous functions in bootstrap.inc.
-   */
-  function testMisc() {
-    // Test drupal_array_merge_deep().
-    $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => 'X', 'class' => array('a', 'b')), 'language' => 'en');
-    $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('c', 'd')), 'html' => TRUE);
-    $expected = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')), 'language' => 'en', 'html' => TRUE);
-    $this->assertIdentical(drupal_array_merge_deep($link_options_1, $link_options_2), $expected, 'drupal_array_merge_deep() returned a properly merged array.');
-  }
-
   /**
    * Tests that the drupal_check_memory_limit() function works as expected.
    */
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
index ede0b0b47f07cf8f7c6948447dfbeffae5277c1a..144e4486b0a559c8ff8c89a55c02fa837ad9f7b9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
@@ -7,12 +7,13 @@
 
 namespace Drupal\system\Tests\Common;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\simpletest\UnitTestBase;
 
 /**
- * Tests the various drupal_array_* helper functions.
+ * Tests the NestedArray helper class.
  */
-class ArrayUnitTest extends UnitTestBase {
+class NestedArrayUnitTest extends UnitTestBase {
 
   /**
    * Form array to check.
@@ -26,8 +27,8 @@ class ArrayUnitTest extends UnitTestBase {
 
   public static function getInfo() {
     return array(
-      'name' => 'drupal_array_*() tests',
-      'description' => 'Tests the various drupal_array_* helper functions.',
+      'name' => 'NestedArray functionality',
+      'description' => 'Tests the NestedArray helper class.',
       'group' => 'System',
     );
   }
@@ -47,42 +48,42 @@ function setUp() {
   /**
    * Tests getting nested array values.
    */
-  function testGet() {
+  function testGetValue() {
     // Verify getting a value of a nested element.
-    $value = drupal_array_get_nested_value($this->form, $this->parents);
+    $value = NestedArray::getValue($this->form, $this->parents);
     $this->assertEqual($value['#value'], 'Nested element', 'Nested element value found.');
 
     // Verify changing a value of a nested element by reference.
-    $value = &drupal_array_get_nested_value($this->form, $this->parents);
+    $value = &NestedArray::getValue($this->form, $this->parents);
     $value['#value'] = 'New value';
-    $value = drupal_array_get_nested_value($this->form, $this->parents);
+    $value = NestedArray::getValue($this->form, $this->parents);
     $this->assertEqual($value['#value'], 'New value', 'Nested element value was changed by reference.');
     $this->assertEqual($this->form['details']['element']['#value'], 'New value', 'Nested element value was changed by reference.');
 
     // Verify that an existing key is reported back.
     $key_exists = NULL;
-    drupal_array_get_nested_value($this->form, $this->parents, $key_exists);
+    NestedArray::getValue($this->form, $this->parents, $key_exists);
     $this->assertIdentical($key_exists, TRUE, 'Existing key found.');
 
     // Verify that a non-existing key is reported back and throws no errors.
     $key_exists = NULL;
     $parents = $this->parents;
     $parents[] = 'foo';
-    drupal_array_get_nested_value($this->form, $parents, $key_exists);
+    NestedArray::getValue($this->form, $parents, $key_exists);
     $this->assertIdentical($key_exists, FALSE, 'Non-existing key not found.');
   }
 
   /**
    * Tests setting nested array values.
    */
-  function testSet() {
+  function testSetValue() {
     $new_value = array(
       '#value' => 'New value',
       '#required' => TRUE,
     );
 
     // Verify setting the value of a nested element.
-    drupal_array_set_nested_value($this->form, $this->parents, $new_value);
+    NestedArray::setValue($this->form, $this->parents, $new_value);
     $this->assertEqual($this->form['details']['element']['#value'], 'New value', 'Changed nested element value found.');
     $this->assertIdentical($this->form['details']['element']['#required'], TRUE, 'New nested element value found.');
   }
@@ -90,19 +91,19 @@ function testSet() {
   /**
    * Tests unsetting nested array values.
    */
-  function testUnset() {
+  function testUnsetValue() {
     // Verify unsetting a non-existing nested element throws no errors and the
     // non-existing key is properly reported.
     $key_existed = NULL;
     $parents = $this->parents;
     $parents[] = 'foo';
-    drupal_array_unset_nested_value($this->form, $parents, $key_existed);
+    NestedArray::unsetValue($this->form, $parents, $key_existed);
     $this->assertTrue(isset($this->form['details']['element']['#value']), 'Outermost nested element key still exists.');
     $this->assertIdentical($key_existed, FALSE, 'Non-existing key not found.');
 
     // Verify unsetting a nested element.
     $key_existed = NULL;
-    drupal_array_unset_nested_value($this->form, $this->parents, $key_existed);
+    NestedArray::unsetValue($this->form, $this->parents, $key_existed);
     $this->assertFalse(isset($this->form['details']['element']), 'Removed nested element not found.');
     $this->assertIdentical($key_existed, TRUE, 'Existing key was found.');
   }
@@ -112,11 +113,34 @@ function testUnset() {
    */
   function testKeyExists() {
     // Verify that existing key is found.
-    $this->assertIdentical(drupal_array_nested_key_exists($this->form, $this->parents), TRUE, 'Nested key found.');
+    $this->assertIdentical(NestedArray::keyExists($this->form, $this->parents), TRUE, 'Nested key found.');
 
     // Verify that non-existing keys are not found.
     $parents = $this->parents;
     $parents[] = 'foo';
-    $this->assertIdentical(drupal_array_nested_key_exists($this->form, $parents), FALSE, 'Non-existing nested key not found.');
+    $this->assertIdentical(NestedArray::keyExists($this->form, $parents), FALSE, 'Non-existing nested key not found.');
+  }
+
+  /**
+   * Tests NestedArray::mergeDeepArray().
+   */
+  function testMergeDeepArray() {
+    $link_options_1 = array(
+      'fragment' => 'x',
+      'attributes' => array('title' => 'X', 'class' => array('a', 'b')),
+      'language' => 'en',
+    );
+    $link_options_2 = array(
+      'fragment' => 'y',
+      'attributes' => array('title' => 'Y', 'class' => array('c', 'd')),
+      'html' => TRUE,
+    );
+    $expected = array(
+      'fragment' => 'y',
+      'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')),
+      'language' => 'en',
+      'html' => TRUE,
+    );
+    $this->assertIdentical(NestedArray::mergeDeepArray(array($link_options_1, $link_options_2)), $expected, 'NestedArray::mergeDeepArray() returned a properly merged array.');
   }
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php
index 103ea43dc4dff96fdba57e23b10eb70681b3cd74..c7bc9676712429baf856482c2406dfe631628eaa 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Plugin\views\query;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Database\Database;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\Core\Database\DatabaseExceptionWrapper;
@@ -254,7 +255,7 @@ public function buildOptionsForm(&$form, &$form_state) {
    */
   public function submitOptionsForm(&$form, &$form_state) {
     $element = array('#parents' => array('query', 'options', 'query_tags'));
-    $value = explode(',', drupal_array_get_nested_value($form_state['values'], $element['#parents']));
+    $value = explode(',', NestedArray::getValue($form_state['values'], $element['#parents']));
     $value = array_filter(array_map('trim', $value));
     form_set_value($element, $value, $form_state);
   }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
index 609b34c5b0f6d9bdcdd6b00c6fa5c54304f7c089..37c00096dfcfb0df37c1130ecc8a16821ecdfb50 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Plugin\views\wizard;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\views\Plugin\Core\Entity\View;
 use Drupal\views_ui\ViewUI;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
@@ -475,7 +476,7 @@ public static function getSelected($form_state, $parents, $default_value, $eleme
     // do for a highly dynamic and extensible form. This method is much simpler.
     if (!empty($form_state['input'])) {
       $key_exists = NULL;
-      $submitted = drupal_array_get_nested_value($form_state['input'], $parents, $key_exists);
+      $submitted = NestedArray::getValue($form_state['input'], $parents, $key_exists);
       // Check that the user-submitted value is one of the allowed options before
       // returning it. This is not a substitute for actual form validation;
       // rather it is necessary because, for example, the same select element
diff --git a/core/modules/views/views_ui/admin.inc b/core/modules/views/views_ui/admin.inc
index c2775e491c22bb06cc20b01b79e4382fb95ea0c6..44ad1ccc3c1dffe992e2637f869ecc25d66b63a8 100644
--- a/core/modules/views/views_ui/admin.inc
+++ b/core/modules/views/views_ui/admin.inc
@@ -5,6 +5,7 @@
  * Provides the Views' administrative interface.
  */
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Database\Database;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Drupal\views_ui\ViewUI;
@@ -150,7 +151,7 @@ function views_ui_add_limited_validation($element, &$form_state) {
   $array_parents = $element['#array_parents'];
   array_pop($array_parents);
   $array_parents[] = $element['#views_ui_ajax_data']['trigger_key'];
-  $ajax_triggering_element = drupal_array_get_nested_value($form_state['complete_form'], $array_parents);
+  $ajax_triggering_element = NestedArray::getValue($form_state['complete_form'], $array_parents);
 
   // Limit this button's validation to the AJAX triggering element, so it can
   // update the form for that change without requiring that the rest of the
@@ -188,7 +189,7 @@ function views_ui_add_ajax_wrapper($element, &$form_state) {
     // This was earlier stored in a property on the element.
     $complete_form = &$form_state['complete_form'];
     $refresh_parents = $element['#views_ui_ajax_data']['refresh_parents'];
-    $refresh_element = drupal_array_get_nested_value($complete_form, $refresh_parents);
+    $refresh_element = NestedArray::getValue($complete_form, $refresh_parents);
 
     // The HTML ID that AJAX expects was also stored in a property on the
     // element, so use that information to insert the wrapper <div> here.
@@ -202,7 +203,7 @@ function views_ui_add_ajax_wrapper($element, &$form_state) {
 
     // Copy the element that needs to be refreshed back into the form, with our
     // modifications to it.
-    drupal_array_set_nested_value($complete_form, $refresh_parents, $refresh_element);
+    NestedArray::setValue($complete_form, $refresh_parents, $refresh_element);
   }
 
   return $element;
@@ -218,7 +219,7 @@ function views_ui_ajax_update_form($form, $form_state) {
   // The region that needs to be updated was stored in a property of the
   // triggering element by views_ui_add_ajax_trigger(), so all we have to do is
   // retrieve that here.
-  return drupal_array_get_nested_value($form, $form_state['triggering_element']['#views_ui_ajax_data']['refresh_parents']);
+  return NestedArray::getValue($form, $form_state['triggering_element']['#views_ui_ajax_data']['refresh_parents']);
 }
 
 /**