diff --git a/core/modules/system/lib/Drupal/system/Plugin/views/display/Data.php b/core/modules/system/lib/Drupal/system/Plugin/views/display/Data.php
new file mode 100644
index 0000000..2fa8194
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/views/display/Data.php
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Plugin\views\display\Data.
+ */
+
+namespace Drupal\system\Plugin\views\display;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+use Drupal\views\Plugin\views\display\PathPluginBase;
+
+/**
+ * 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.
+   *
+   * @var bool
+   */
+  protected $usesAJAX = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesPager.
+   *
+   * @var bool
+   */
+  protected $usesPager = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::$usesMore.
+   *
+   * @var bool
+   */
+  protected $usesMore = 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'] = array(
+      'contains' => array(
+        'type' => array('default' => 'json'),
+        'options' => array('default' => array()),
+      ),
+    );
+    $options['row'] = array(
+      'contains' => array(
+        'type' => array('default' => 'data_entity'),
+        'options' => array('default' => array()),
+      ),
+    );
+
+dpm($options);
+
+    return $options;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\PathPluginBase::optionsSummary().
+   */
+  public function optionsSummary(&$categories, &$options) {
+    parent::optionsSummary($categories, $options);
+
+    unset($categories['page']);
+    unset($options['hide_admin_links'], $options['analyze-theme']);
+
+    $categories['json'] = array(
+      'title' => t('Json settings'),
+      'column' => 'second',
+      'build' => array(
+        '#weight' => -10,
+      ),
+    );
+
+    $options['path']['category'] = 'json';
+    $options['path']['title'] = t('JSON');
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::buildOptionsForm().
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::validateOptionsForm().
+   */
+  public function validateOptionsForm(&$form, &$form_state) {
+    parent::validateOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase:submitOptionsForm().
+   */
+  public function submitOptionsForm(&$form, &$form_state) {
+    parent::submitOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\PathPluginBase::execute().
+   */
+  public function execute() {
+    parent::execute();
+
+    $this->view->execute();
+    return $this->render();
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::render().
+   */
+  public function render() {
+    return $this->view->style_plugin->render();
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\display\DisplayPluginBase::preview().
+   */
+  public function preview() {
+    $this->view->execute();
+
+    if (!empty($this->view->result)) {
+      $this->view->style_plugin->preview = TRUE;
+      return $this->view->style_plugin->render();
+    }
+
+    return '';
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/views/row/DataEntityRow.php b/core/modules/system/lib/Drupal/system/Plugin/views/row/DataEntityRow.php
new file mode 100644
index 0000000..8b9aaad
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/views/row/DataEntityRow.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Plugin\views\row\DataEntityRow.
+ */
+
+namespace Drupal\system\Plugin\views\row;
+
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+use Drupal\views\Plugin\views\row\RowPluginBase;
+
+/**
+ * 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 {
+
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    return $options;
+  }
+
+  /**
+   * Provide a form for setting options.
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Validate the options form.
+   */
+  public function validateOptionsForm(&$form, &$form_state) {}
+
+  /**
+   * Perform any necessary changes to the form values prior to storage.
+   * There is no need for this function to actually store the data.
+   */
+  public function submitOptionsForm(&$form, &$form_state) {}
+
+  /**
+   * Overrides Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function render($row) {
+    return $row->_entity;
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/system/lib/Drupal/system/Plugin/views/row/DataFieldRow.php b/core/modules/system/lib/Drupal/system/Plugin/views/row/DataFieldRow.php
new file mode 100644
index 0000000..bf5df2a
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/views/row/DataFieldRow.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Plugin\views\row\DataFieldRow.
+ */
+
+namespace Drupal\system\Plugin\views\row;
+
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+use Drupal\views\Plugin\views\row\RowPluginBase;
+
+/**
+ * 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 {
+
+  /**
+   * Does the row plugin support to add fields to it's output.
+   *
+   * @var bool
+   */
+  protected $usesFields = TRUE;
+
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    return $options;
+  }
+
+  /**
+   * Provide a form for setting options.
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+  }
+
+  /**
+   * Validate the options form.
+   */
+  public function validateOptionsForm(&$form, &$form_state) {}
+
+  /**
+   * Perform any necessary changes to the form values prior to storage.
+   * There is no need for this function to actually store the data.
+   */
+  public function submitOptionsForm(&$form, &$form_state) {}
+
+  /**
+   * Overrides Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function render($row) {
+    foreach ($this->view->field as $id => $field) {
+      $output[$field->field_alias] = $row->{$field->field_alias};
+    }
+
+    return $output;
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/system/lib/Drupal/system/Plugin/views/style/Json.php b/core/modules/system/lib/Drupal/system/Plugin/views/style/Json.php
new file mode 100644
index 0000000..cc138d4
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/views/style/Json.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\system\Plugin\views\style\Json.
+ */
+
+namespace Drupal\system\Plugin\views\style;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+use Drupal\views\Plugin\views\style\StylePluginBase;
+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;
+
+  /**
+   * Stores whether the style plugin is being called in a preview context.
+   *
+   * @var bool
+   */
+  public $preview = FALSE;
+
+  /**
+   *
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    return $options;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::buildOptionsForm().
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+  }
+
+  /**
+   * 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 = new JsonResponse($rows);
+
+    return $this->preview ? $response->getContent() : $response;
+  }
+
+}
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..02717d9
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayJsonTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\Tests\Plugin\DisplayJsonTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\views\Tests\Plugin\PluginTestBase;
+
+/**
+ * Tests the JSON display plugin.
+ *
+ * @see Drupal\views\Plugin\display\Json
+ */
+class DisplayJsonTest extends PluginTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Display: JSON plugin',
+      'description' => 'Tests the JSON display plugin.',
+      'group' => 'Views Plugins',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    for ($i = 1; $i <= 10; $i++) {
+      $this->drupalCreateNode();
+    }
+
+    $this->enableViewsTestModule();
+  }
+
+  /**
+   * Checks the behavior of JSON callback paths.
+   */
+  public function testJsonResponses() {
+    $view = views_get_view('test_json_display');
+    $view->initDisplay();
+    $this->executeView($view);
+
+    // Test the JSON callback.
+    $actual_json = $this->drupalGet('test/json');
+    $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 $result) {
+      $expected[] = $result->_entity;
+    }
+
+    $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);
+  }
+
+}
diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_json_display.yml b/core/modules/views/tests/views_test_config/config/views.view.test_json_display.yml
new file mode 100644
index 0000000..8644ebe
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_json_display.yml
@@ -0,0 +1,74 @@
+base_table: views_test_data
+name: test_json_display
+description: ''
+tag: ''
+human_name: 'Test JSON display'
+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: 'view published content'
+      cache:
+        type: none
+      query:
+        type: views_query
+      exposed_form:
+        type: basic
+      pager:
+        type: full
+        options:
+          items_per_page: '10'
+      style:
+        type: json
+      row:
+        type: data_entity
+      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: {  }
+  json_1:
+    display_plugin: data
+    id: json_1
+    display_title: Json
+    position: ''
+    display_options:
+      defaults:
+        access: false
+      path: test/json
+      access:
+        type: none
+  json_2:
+    display_plugin: data
+    id: json_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
