3 namespace Drupal\migrate_plus\Plugin\migrate_plus\data_parser;
5 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
6 use Drupal\migrate_plus\DataParserPluginBase;
9 * Obtain JSON data for migration.
13 * title = @Translation("JSON")
16 class Json extends DataParserPluginBase implements ContainerFactoryPluginInterface {
19 * The request headers passed to the data fetcher.
23 protected $headers = [];
26 * Iterator over the JSON data.
33 * Retrieves the JSON data and returns it as an array.
39 * The selected data to be iterated.
41 * @throws \GuzzleHttp\Exception\RequestException
43 protected function getSourceData($url) {
44 $response = $this->getDataFetcherPlugin()->getResponseContent($url);
46 // json_decode() expects utf8 data so let's make sure it gets it.
47 $utf8response = utf8_encode($response);
49 // Convert objects to associative arrays.
50 $source_data = json_decode($utf8response, TRUE);
51 // Backwards-compatibility for depth selection.
52 if (is_int($this->itemSelector)) {
53 return $this->selectByDepth($source_data);
56 // Otherwise, we're using xpath-like selectors.
57 $selectors = explode('/', trim($this->itemSelector, '/'));
58 foreach ($selectors as $selector) {
59 $source_data = $source_data[$selector];
65 * Get the source data for reading.
67 * @param array $raw_data
68 * Raw data from the JSON feed.
71 * Selected items at the requested depth of the JSON feed.
73 protected function selectByDepth(array $raw_data) {
74 // Return the results in a recursive iterator that can traverse
75 // multidimensional arrays.
76 $iterator = new \RecursiveIteratorIterator(
77 new \RecursiveArrayIterator($raw_data),
78 \RecursiveIteratorIterator::SELF_FIRST);
80 // Backwards-compatibility - an integer item_selector is interpreted as a
81 // depth. When there is an array of items at the expected depth, pull that
82 // array out as a distinct item.
83 $identifierDepth = $this->itemSelector;
85 while ($iterator->valid()) {
86 $item = $iterator->current();
87 if (is_array($item) && $iterator->getDepth() == $identifierDepth) {
98 protected function openSourceUrl($url) {
99 // (Re)open the provided URL.
100 $source_data = $this->getSourceData($url);
101 $this->iterator = new \ArrayIterator($source_data);
108 protected function fetchNextRow() {
109 $current = $this->iterator->current();
111 foreach ($this->fieldSelectors() as $field_name => $selector) {
112 $field_data = $current;
113 $field_selectors = explode('/', trim($selector, '/'));
114 foreach ($field_selectors as $field_selector) {
115 $field_data = $field_data[$field_selector];
117 $this->currentItem[$field_name] = $field_data;
119 if (!empty($this->configuration['include_raw_data'])) {
120 $this->currentItem['raw'] = $current;
122 $this->iterator->next();