diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/Attachment.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/Attachment.php
index a0f6a2f..3838639 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/display/Attachment.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Attachment.php
@@ -90,8 +90,8 @@ public function optionsSummary(&$categories, &$options) {
     }
     elseif (count($displays) == 1) {
       $display = array_shift($displays);
-      if (!empty($this->view->display[$display])) {
-        $attach_to = check_plain($this->view->display[$display]['display_title']);
+      if (!empty($this->view->storage->display[$display])) {
+        $attach_to = check_plain($this->view->storage->display[$display]['display_title']);
       }
     }
 
@@ -193,7 +193,7 @@ public function buildOptionsForm(&$form, &$form_state) {
       case 'displays':
         $form['#title'] .= t('Attach to');
         $displays = array();
-        foreach ($this->view->display as $display_id => $display) {
+        foreach ($this->view->storage->display as $display_id => $display) {
           if (!empty($this->view->displayHandlers[$display_id]) && $this->view->displayHandlers[$display_id]->acceptAttachments()) {
             $displays[$display_id] = $display['display_title'];
           }
@@ -249,8 +249,8 @@ public function attachTo($display_id) {
     $view->setArguments($args);
     $view->setDisplay($this->display['id']);
     if ($this->getOption('inherit_pager')) {
-      $view->display_handler->usesPager = $this->view->display[$display_id]->handler->usesPager();
-      $view->display_handler->setOption('pager', $this->view->display[$display_id]->handler->getOption('pager'));
+      $view->display_handler->usesPager = $this->view->displayHandlers[$display_id]->usesPager();
+      $view->display_handler->setOption('pager', $this->view->displayHandlers[$display_id]->getOption('pager'));
     }
 
     $attachment = $view->executeDisplay($this->display['id'], $args);
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/Data.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/Data.php
new file mode 100644
index 0000000..ce02711
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Data.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\display\Data.
+ */
+
+namespace Drupal\views\Plugin\views\display;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * The plugin that handles a Data response callbacks.
+ *
+ * @ingroup views_display_plugins
+ *
+ * @Plugin(
+ *   id = "data",
+ *   title = @Translation("Data"),
+ *   help = @Translation("Display views as data output formats"),
+ *   uses_hook_menu = TRUE,
+ *   admin = @Translation("Data")
+ * )
+ */
+class Data extends PathPluginBase {
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesAJAX.
+   */
+  protected $usesAJAX = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesPager.
+   */
+  protected $usesPager = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesMore.
+   */
+  protected $usesMore = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesAreas.
+   */
+  protected $usesAreas = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesAreas.
+   */
+  protected $usesOptions = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::getStyleType().
+   */
+  protected function getStyleType() {
+    return 'data';
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::usesExposed().
+   */
+  public function usesExposed() {
+    return FALSE;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::displaysExposed().
+   */
+  public function displaysExposed() {
+    return FALSE;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::defineOptions().
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+
+    // Set the default style plugin to 'json'.
+    $options['style']['contains']['type']['default'] = 'json';
+    $options['row']['contains']['type']['default'] = 'data_entity';
+    $options['defaults']['default']['style'] = FALSE;
+    $options['defaults']['default']['row'] = FALSE;
+
+    return $options;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\PathPluginBase::optionsSummary().
+   */
+  public function optionsSummary(&$categories, &$options) {
+    parent::optionsSummary($categories, $options);
+
+    unset($categories['page']);
+    // Hide some settings, as they aren't useful for pure data output.
+    unset($options['hide_admin_links'], $options['analyze-theme']);
+
+    $categories['path'] = array(
+      'title' => t('Path settings'),
+      'column' => 'second',
+      'build' => array(
+        '#weight' => -10,
+      ),
+    );
+
+    $options['path']['category'] = 'path';
+    $options['path']['title'] = t('Path');
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\PathPluginBase::execute().
+   */
+  public function execute() {
+    parent::execute();
+    $output = $this->view->render();
+
+    $response = $this->view->getResponse();
+    $response->setContent($output);
+
+    return $response;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::render().
+   */
+  public function render() {
+    $output = $this->view->style_plugin->render();
+    if (!empty($this->view->live_preview)) {
+      return '<pre>' . $output . '</pre>';
+    }
+    return $output;
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/row/DataEntityRow.php b/core/modules/views/lib/Drupal/views/Plugin/views/row/DataEntityRow.php
new file mode 100644
index 0000000..c635e5e
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/row/DataEntityRow.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\row\DataEntityRow.
+ */
+
+namespace Drupal\views\Plugin\views\row;
+
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Plugin which displays entities as raw data.
+ *
+ * @ingroup views_row_plugins
+ *
+ * @Plugin(
+ *   id = "data_entity",
+ *   module = "system",
+ *   title = @Translation("Entity"),
+ *   help = @Translation("Use entities as row data."),
+ *   type = "data"
+ * )
+ */
+class DataEntityRow extends RowPluginBase {
+
+  /**
+   * Overrides Drupal\views\Plugin\Plugin::$usesOptions.
+   */
+  protected $usesOptions = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function render($row) {
+    return $row->_entity;
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/row/DataFieldRow.php b/core/modules/views/lib/Drupal/views/Plugin/views/row/DataFieldRow.php
new file mode 100644
index 0000000..22a3a02
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/row/DataFieldRow.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\row\DataFieldRow.
+ */
+
+namespace Drupal\views\Plugin\views\row;
+
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Plugin which displays fields as raw data.
+ *
+ * @ingroup views_row_plugins
+ *
+ * @Plugin(
+ *   id = "data_field",
+ *   module = "system",
+ *   title = @Translation("Fields"),
+ *   help = @Translation("Use fields as row data."),
+ *   type = "data"
+ * )
+ */
+class DataFieldRow extends RowPluginBase {
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::$usesFields.
+   *
+   * @var bool
+   */
+  protected $usesFields = TRUE;
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+
+    $form['aliases'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Field ID aliases'),
+      '#description' => t('Rename views default field ID\'s in the output data.'),
+      '#tree' => TRUE,
+    );
+
+    if ($fields = $this->view->display_handler->getOption('fields')) {
+      $options = $this->options;
+
+      foreach ($fields as $id => $field) {
+        $form['aliases'][$id] = array(
+          '#type' => 'textfield',
+          '#title' => $id,
+          '#default_value' => isset($options['aliases'][$id]) ? $options['aliases'][$id] : '',
+        );
+      }
+    }
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function render($row) {
+    $ouput = array();
+
+    foreach ($this->view->field as $id => $field) {
+      $output[$this->getFieldKeyAlias($id)] = $row->{$field->field_alias};
+    }
+
+    return $output;
+  }
+
+  /**
+   * Return an alias for a field ID, as set in the options form.
+   *
+   * @param string $id
+   *   The field id to lookup an alias for.
+   *
+   * @return string
+   *   The matches user entered alias, or the original ID if nothing is found.
+   */
+  public function getFieldKeyAlias($id) {
+    if (isset($this->options['aliases'][$id])) {
+      return trim($this->options['aliases'][$id]);
+    }
+    return $id;
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Json.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Json.php
new file mode 100644
index 0000000..d29c2b6
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Json.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\style\Json.
+ */
+
+namespace Drupal\views\Plugin\views\style;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Translation;
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * The style plugin for views JSON output.
+ *
+ * @ingroup views_style_plugins
+ *
+ * @Plugin(
+ *   id = "json",
+ *   title = @Translation("JSON"),
+ *   help = @Translation("Manages the data contained in JSON output rows."),
+ *   type = "data"
+ * )
+ */
+class Json extends StylePluginBase {
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesRowPlugin.
+   */
+  protected $usesRowPlugin = TRUE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesFields.
+   */
+  protected $usesFields = TRUE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesFields.
+   */
+  protected $usesGrouping = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesFields.
+   */
+  protected $usesOptions = FALSE;
+
+  public function init(ViewExecutable $view, &$display, $options = NULL) {
+    parent::init($view, $display, $options);
+
+    $response = new JsonResponse();
+    $this->view->setResponse($response);
+  }
+
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::render().
+   */
+  public function render() {
+    $rows = array();
+
+    foreach ($this->view->result as $row) {
+      $rows[] = $this->row_plugin->render($row);
+    }
+    $response = $this->view->getResponse();
+    $response->setData($rows);
+
+    return $response->getContent();
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayJsonTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayJsonTest.php
new file mode 100644
index 0000000..6558195
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayJsonTest.php
@@ -0,0 +1,125 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\Tests\Plugin\DisplayJsonTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\views\Tests\Plugin\PluginTestBase;
+
+/**
+ * Tests the JSON style plugin.
+ *
+ * @see Drupal\views\Plugin\display\Json
+ */
+class DisplayJsonTest extends PluginTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('views_ui', 'node');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Style: JSON plugin',
+      'description' => 'Tests the JSON style plugin.',
+      'group' => 'Views Plugins',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    for ($i = 1; $i <= 10; $i++) {
+      $this->drupalCreateNode();
+    }
+
+    $this->enableViewsTestModule();
+
+    $this->adminUser = $this->drupalCreateUser(array('administer views', 'bypass node access', 'access user profiles', 'view revisions'));
+  }
+
+  /**
+   * Checks the behavior of JSON callback paths and row plugins.
+   */
+  public function testJsonResponses() {
+    $view = views_get_view('test_json_display_field');
+    $view->initDisplay();
+    $this->executeView($view);
+
+    // Test the JSON callback.
+    $actual_json = $this->drupalGet('test/json/field');
+    $this->assertResponse(200);
+
+    // Test the http content-type.
+    $headers = $this->drupalGetHeaders();
+    $this->assertEqual($headers['content-type'], 'application/json', 'The header content-type is correct.');
+
+    $expected = array();
+    foreach ($view->result as $row) {
+      $expected_row = array();
+      foreach ($view->field as $id => $field) {
+        $expected_row[$id] = $row->{$field->field_alias};
+      }
+      $expected[] = $expected_row;
+    }
+
+    $this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.');
+
+    // Test a 403 callback.
+    $this->drupalGet('test/json/denied');
+    $this->assertResponse(403);
+
+    // Test the entity rows.
+    $view = views_get_view('test_json_display_entity');
+    $view->initDisplay();
+    $this->executeView($view);
+
+    $actual_json = $this->drupalGet('test/json/entity');
+    $this->assertResponse(200);
+
+    $expected = array();
+    foreach ($view->result as $row) {
+      $expected[] = $row->_entity;
+    }
+
+    $this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.');
+  }
+
+  /**
+   * Test the field ID alias functionality of the DataFieldRow plugin.
+   */
+  public function testUIFieldAlias() {
+    $this->drupalLogin($this->adminUser);
+
+    // Test the UI settings for adding field ID aliases.
+    $this->drupalGet('admin/structure/views/view/test_json_display_field/edit/data_1');
+    $row_options = 'admin/structure/views/nojs/display/test_json_display_field/data_1/row_options';
+    $this->assertLinkByHref($row_options);
+
+    // Add a random alias for the name field and save the view.
+    $random_name = $this->randomName();
+    $this->drupalPost($row_options, array('row_options[aliases][name]' => $random_name), t('Apply'));
+    $this->drupalPost(NULL, array(), t('Save'));
+
+    $view = views_get_view('test_json_display_field');
+    $view->setDisplay('data_1');
+    $this->executeView($view);
+
+    $expected = array();
+    foreach ($view->result as $row) {
+      $expected_row = array();
+      foreach ($view->field as $id => $field) {
+        $expected_row[$random_name] = $row->{$field->field_alias};
+      }
+      $expected[] = $expected_row;
+    }
+
+    $this->assertIdentical($this->drupalGet('test/json/field'), json_encode($expected));
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Tests/UI/DisplayAttachmentTest.php b/core/modules/views/lib/Drupal/views/Tests/UI/DisplayAttachmentTest.php
new file mode 100644
index 0000000..eb437f4
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/UI/DisplayAttachmentTest.php
@@ -0,0 +1,31 @@
+<?php
+
+  /**
+   * @file
+   * Definition of Drupal\views\Tests\UI\DisplayAttachmentTest.
+   */
+
+namespace Drupal\views\Tests\UI;
+
+/**
+ * Tests the UI for the attachment display plugin.
+ *
+ * @see Drupal\views\Plugin\views\display\Attachment
+ */
+class DisplayAttachmentTest extends UITestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Display: Attachment',
+      'description' => 'Tests the UI for the attachment display plugin.',
+      'group' => 'Views UI',
+    );
+  }
+
+  /**
+   * Tests the attachment UI.
+   */
+  public function testAttachmentUI() {
+    $view = views_get_view('test_attachment_ui');
+  }
+}
diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php
index 4e59f7f..3f2f3cb 100644
--- a/core/modules/views/lib/Drupal/views/ViewExecutable.php
+++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php
@@ -1239,9 +1239,6 @@ public function render($display_id = NULL) {
     drupal_theme_initialize();
     $config = config('views.settings');
 
-    // Set the response so other parts can alter it.
-    $this->response = new Response('', 200);
-
     $start = microtime(TRUE);
     if (!empty($this->live_preview) && $config->get('ui.show.additional_queries')) {
       $this->startQueryCapture();
@@ -1272,6 +1269,11 @@ public function render($display_id = NULL) {
       // Initialize the style plugin.
       $this->initStyle();
 
+      if (!isset($this->response)) {
+        // Set the response so other parts can alter it.
+        $this->response = new Response('', 200);
+      }
+
       // Give field handlers the opportunity to perform additional queries
       // using the entire resultset prior to rendering.
       if ($this->style_plugin->usesFields()) {
diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_attachment_ui.yml b/core/modules/views/tests/views_test_config/config/views.view.test_attachment_ui.yml
new file mode 100644
index 0000000..d21b866
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_attachment_ui.yml
@@ -0,0 +1,33 @@
+api_version: '3.0'
+base_table: node
+core: '8'
+description: ''
+disabled: '0'
+display:
+  default:
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'views_test_data test permission'
+      cache:
+        type: none
+      exposed_form:
+        type: basic
+      pager:
+        type: full
+      style:
+        type: default
+      row:
+        type: fields
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: '0'
+  attachment_1:
+    display_plugin: attachment
+    display_title: Attachment
+    id: attachment_1
+
+name: test_attachment_ui
+tag: ''
diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_json_display_entity.yml b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_entity.yml
new file mode 100644
index 0000000..a6be457
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_entity.yml
@@ -0,0 +1,55 @@
+base_table: node
+name: test_json_display_entity
+description: ''
+tag: ''
+human_name: 'Test JSON display entity rows'
+core: 8.x
+api_version: '3.0'
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: ''
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: none
+      query:
+        type: views_query
+      exposed_form:
+        type: basic
+      style:
+        type: json
+      row:
+        type: data_entity
+      sorts:
+        created:
+          id: created
+          table: node
+          field: created
+          order: DESC
+      title: 'Test JSON'
+      arguments: {  }
+  data_1:
+    display_plugin: data
+    id: data_1
+    display_title: Json
+    position: ''
+    display_options:
+      defaults:
+        access: false
+        style: false
+        row: false
+      style:
+        type: json
+      row:
+        type: data_entity
+      path: test/json/entity
+base_field: nid
+disabled: '0'
+module: views
+langcode: und
diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_json_display_field.yml b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_field.yml
new file mode 100644
index 0000000..f74d4fd
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_field.yml
@@ -0,0 +1,82 @@
+base_table: views_test_data
+name: test_json_display_field
+description: ''
+tag: ''
+human_name: 'Test JSON display field rows'
+core: 8.x
+api_version: '3.0'
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: ''
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: none
+      query:
+        type: views_query
+      exposed_form:
+        type: basic
+      style:
+        type: json
+      row:
+        type: data_field
+      fields:
+        name:
+          id: name
+          table: views_test_data
+          field: name
+          label: ''
+      sorts:
+        created:
+          id: created
+          table: views_test_data
+          field: created
+          order: DESC
+      title: 'Test JSON'
+      arguments: {  }
+  data_1:
+    display_plugin: data
+    id: data_1
+    display_title: Json
+    position: ''
+    display_options:
+      defaults:
+        access: false
+        style: false
+        row: false
+      style:
+        type: json
+      row:
+        type: data_field
+      path: test/json/field
+      access:
+        type: none
+  data_2:
+    display_plugin: data
+    id: data_2
+    display_title: 'Json - access denied'
+    position: ''
+    display_options:
+      defaults:
+        access: false
+        style: false
+        row: false
+      style:
+        type: json
+      row:
+        type: data_field
+      path: test/json/denied
+      access:
+        type: perm
+        options:
+          perm: 'administer views'
+base_field: id
+disabled: '0'
+module: views
+langcode: und
