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..a9447b2
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Data.php
@@ -0,0 +1,128 @@
+<?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::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'] = 'json';
+    $options['row']['contains']['type'] = 'data_entity';
+
+    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..deddee3
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Json.php
@@ -0,0 +1,73 @@
+<?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.
+   *
+   * @var bool
+   */
+  protected $usesRowPlugin = TRUE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesFields.
+   *
+   * @var bool
+   */
+  protected $usesFields = TRUE;
+
+  /**
+   * Does the style plugin support grouping of rows.
+   *
+   * @var bool
+   */
+  protected $usesGrouping = 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/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_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..49efa18
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_entity.yml
@@ -0,0 +1,49 @@
+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
+      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..b62cb3b
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_json_display_field.yml
@@ -0,0 +1,70 @@
+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
+      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
+      path: test/json/denied
+      access:
+        type: perm
+        options:
+          perm: 'administer views'
+base_field: id
+disabled: '0'
+module: views
+langcode: und
