diff --git a/src/Plugin/migrate_plus/data_parser/Json.php b/src/Plugin/migrate_plus/data_parser/Json.php
index d8292ae..87a8fe3 100755
--- a/src/Plugin/migrate_plus/data_parser/Json.php
+++ b/src/Plugin/migrate_plus/data_parser/Json.php
@@ -30,27 +30,36 @@ class Json extends DataParserPluginBase implements ContainerFactoryPluginInterfa
   protected $iterator;
 
   /**
+   * Tracks retrieved URLs.
+   *
+   * @var array
+   */
+  protected $checked = [];
+
+  /**
    * Retrieves the JSON data and returns it as an array.
    *
    * @param string $url
    *   URL of a JSON feed.
+   * @param $item_selector
+   *   Selector within the data content at which useful data is found.
    *
    * @return array
    *   The selected data to be iterated.
    *
    * @throws \GuzzleHttp\Exception\RequestException
    */
-  protected function getSourceData($url) {
+  protected function getSourceData($url, $item_selector = '') {
     $response = $this->getDataFetcherPlugin()->getResponseContent($url);
     // Convert objects to associative arrays.
     $source_data = json_decode($response, TRUE);
     // Backwards-compatibility for depth selection.
-    if (is_int($this->itemSelector)) {
+    if (is_int($item_selector)) {
       return $this->selectByDepth($source_data);
     }
 
     // Otherwise, we're using xpath-like selectors.
-    $selectors = explode('/', trim($this->itemSelector, '/'));
+    $selectors = explode('/', trim($this->item_selector, '/'));
     foreach ($selectors as $selector) {
       $source_data = $source_data[$selector];
     }
@@ -93,7 +102,7 @@ class Json extends DataParserPluginBase implements ContainerFactoryPluginInterfa
    */
   protected function openSourceUrl($url) {
     // (Re)open the provided URL.
-    $source_data = $this->getSourceData($url);
+    $source_data = $this->getSourceData($url, $this->itemSelector);
     $this->iterator = new \ArrayIterator($source_data);
     return TRUE;
   }
@@ -104,16 +113,117 @@ class Json extends DataParserPluginBase implements ContainerFactoryPluginInterfa
   protected function fetchNextRow() {
     $current = $this->iterator->current();
     if ($current) {
+      if (!empty($this->configuration['list'])) {
+        $current = $this->retrieveRemoteItemData($current, $this->configuration['list']);
+      }
       foreach ($this->fieldSelectors() as $field_name => $selector) {
-        $field_data = $current;
-        $field_selectors = explode('/', trim($selector, '/'));
-        foreach ($field_selectors as $field_selector) {
-          $field_data = $field_data[$field_selector];
-        }
+        $field_data = static::select($current, $selector);
         $this->currentItem[$field_name] = $field_data;
       }
       $this->iterator->next();
     }
   }
 
+  /**
+   * Handle "list" mode in the source data.
+   *
+   * A list-enabled source will contain data which uniquely identifies a remote
+   * object which is the intended item for import.
+   *
+   * @param array|bool $options
+   *   In cases where the list mode is simply activated, the row of data will be
+   *   treated as a simple URI to be followed. As an array, there are several
+   *   specific options that will be applied.
+   *     - lookup_selector: Operates as the "field selector" for which value to
+   *       use within the data to derive a URI.
+   *     - remote_item_selector: Similar to item_selector in the source
+   *       configuration, but used to extract the correct data from the remote
+   *       source.
+   *     - uri_template: URI Template to slot ID values into a coherent URL.
+   *
+   * @throws \Exception
+   */
+  protected function getRemoteItemData($data, $options = TRUE) {
+    // Lookup relevant data within the row.
+    if (is_array($data) && isset($options['lookup_selector'])) {
+      $data = static::select($data, $options['lookup_selector']);
+    }
+
+    // Construct the URI at which the data for the specific object may be found.
+    if (isset($options['uri_template'])) {
+      $uri = $this->getListUri($options['uri_template'], $data);
+    }
+    else {
+      $uri = $data;
+    }
+    if (!is_string($uri)) {
+      throw new \Exception('Invalid format for a URI.');
+    }
+
+    $item_selector = isset($options['remote_item_selector']) ? $options['remote_item_selector'] : $this->itemSelector;
+
+    // Provide some minimum feedback that this specific data value was
+    // previously targeted for retrieval.
+    if (isset($this->checked[$uri . $item_selector])) {
+      \Drupal::logger('migrate')->notice('The URI %uri was previously retrieved for selector %selector.', [
+        '%uri' => $uri,
+        '%selector' => $item_selector,
+      ]);
+    }
+    $this->checked[$uri . $item_selector] = TRUE;
+
+    return $this->getSourceData($uri, $item_selector);
+  }
+
+  /**
+   * Generate a URI based on data and a URI template.
+   *
+   * @param string $template
+   *   URI template. If it lacks curly-brace delimited items and $variables
+   *   is scalar the $variables value will be appended to the template.
+   *   Otherwise named elements on $variables will be replaced.
+   * @param mixed $variables
+   *   If a scalar this will be appended to the template. If an array, named
+   *   elements will be used as data source for replacement in the template.
+   *
+   * @return string
+   *   Processed link template.
+   *
+   * @todo find a dedicated facility for link template logic.
+   */
+  protected function getListUri($template, $variables) {
+    if (strpos($template, '{') === FALSE && is_scalar($variables)) {
+      return $template . $variables;
+    }
+    elseif (strpos($template, '{') !== FALSE && is_array($variables)) {
+      foreach ($variables as $key => $value) {
+        if (is_scalar($value)) {
+          $template = preg_replace_all('/\{' . preg_escape($key) . '\}/', $value, $template);
+        }
+      }
+    }
+
+    return $template;
+  }
+
+  /**
+   * Provide xpath-like dereferencing of objects from an array.
+   *
+   * @param array $data
+   *   The data from which we extract our value.
+   * @param string $selector
+   *   Selector in the format of "one/0/id"
+   *
+   * @return mixed
+   *   Value found in the data for the provided selector.
+   */
+  protected static function select(array $data = [], $selector) {
+    $field_selectors = explode('/', trim($selector, '/'));
+    foreach ($field_selectors as $field_selector) {
+      $data = $data[$field_selector];
+    }
+
+    return $data;
+  }
+
 }
