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..d10ac75
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Data.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\display\Data.
+ */
+
+namespace Drupal\views\Plugin\views\display;
+
+use Symfony\Component\HttpFoundation\Response;
+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 the content type of the data response, if needed.
+   */
+  protected $contentType;
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Sets the request content type.
+   */
+  public function setContentType($content_type) {
+    $this->contentType = $content_type;
+  }
+
+  /**
+   * Gets the request content type.
+   *
+   * This will return the overriden content type if set, otherwise returns the
+   * content type from the request.
+   */
+  public function getContentType() {
+    if (isset($this->contentType)) {
+      return $this->contentType;
+    }
+
+    // Return the content type from the request object.
+    return drupal_container()->get('request')->headers->get('Content-type');
+  }
+
+  /**
+   * 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'] = 'serialize';
+    $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 = new Response($output, 200, array('Content-type' => $this->getContentType()));
+
+    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..bbd0aa7
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/row/DataFieldRow.php
@@ -0,0 +1,124 @@
+<?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.
+   */
+  protected $usesFields = TRUE;
+
+  /**
+   * Stores an array of prepared field aliases from options.
+   *
+   * @var array
+   */
+  protected $replacementAliases = array();
+
+  public function init(ViewExecutable $view, &$display, $options = NULL) {
+    parent::init($view, $display, $options);
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::buildOptionsForm().
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    $options['aliases'] = array('default' => array());
+
+    return $options;
+  }
+
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::buildOptionsForm().
+   */
+  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::validateOptionsForm().
+   */
+  public function validateOptionsForm(&$form, &$form_state) {
+    $aliases = $form_state['values']['row_options']['aliases'];
+    if (array_unique($aliases) !== $aliases) {
+      form_set_error('aliases', t('All field aliases must be unique'));
+    }
+
+    // Prepare a trimmed version of replacement aliases.
+    $form_state['values']['row_options']['aliases'] = array_map('trim', (array) $form_state['values']['row_options']['aliases']);
+  }
+
+  /**
+   * Overrides \Drupal\views\Plugin\views\row\RowPluginBase::render().
+   */
+  public function render($row) {
+    $output = 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->replacementAliases[$id])) {
+      return $this->replacementAliases[$id];
+    }
+    return $id;
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Serialize.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Serialize.php
new file mode 100644
index 0000000..010c876
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Serialize.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\views\Plugin\views\style\Serialize.
+ */
+
+namespace Drupal\views\Plugin\views\style;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * The style plugin for serialized output formats.
+ *
+ * @ingroup views_style_plugins
+ *
+ * @Plugin(
+ *   id = "serialize",
+ *   title = @Translation("Serializer"),
+ *   help = @Translation("Serializes views row data using the Serializer component."),
+ *   type = "data"
+ * )
+ */
+class Serialize extends StylePluginBase {
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesRowPlugin.
+   */
+  protected $usesRowPlugin = TRUE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::$usesFields.
+   */
+  protected $usesGrouping = FALSE;
+
+  /**
+   * Overrides Drupal\views\Plugin\views\style\StylePluginBase::render().
+   */
+  public function render() {
+    // Get the Serializer service.
+    $serializer = drupal_container()->get('serializer');
+    $rows = array();
+
+    // If the Data Entity row plugin is used, this will be an array of entities
+    // which will pass through Serializer to one of the registered Normalizers,
+    // which will transform it to arrays/scalars. If the Data Field row plugin
+    // is used, $rows will not contain objects and will pass directly to the
+    // Encoder.
+    foreach ($this->view->result as $row) {
+      $rows[] = $this->row_plugin->render($row);
+    }
+
+    return $serializer->serialize($rows, drupal_container()->get('request')->headers->get('Content-type'));
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleSerializeTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleSerializeTest.php
new file mode 100644
index 0000000..813510b
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleSerializeTest.php
@@ -0,0 +1,127 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\Tests\Plugin\StyleSerializeTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\views\Tests\Plugin\PluginTestBase;
+
+/**
+ * Tests the serialize style plugin.
+ *
+ * @see \Drupal\views\Plugin\display\Data
+ * @see \Drupal\views\Plugin\style\Serialize
+ */
+class StyleSerializeTest extends PluginTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('views_ui', 'node');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Style: Serialize plugin',
+      'description' => 'Tests the serialize 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 serialize callback paths and row plugins.
+   */
+  public function testSerializeResponses() {
+    // Test the serialize callback.
+    $view = views_get_view('test_serialize_display_field');
+    $view->initDisplay();
+    $this->executeView($view);
+
+    $actual_json = $this->drupalGet('test/serialize/field', array(), array('Content-type: application/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 $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/serialize/denied');
+    $this->assertResponse(403);
+
+    // Test the entity rows.
+
+    $view = views_get_view('test_serialize_display_entity');
+    $view->initDisplay();
+    $this->executeView($view);
+
+    $expected = array();
+    foreach ($view->result as $row) {
+      $expected[] = $row->_entity;
+    }
+
+    $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Content-type: application/json'));
+    $this->assertResponse(200);
+
+    $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_serialize_display_field/edit/data_1');
+    $row_options = 'admin/structure/views/nojs/display/test_serialize_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_serialize_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/serialize/field', array(), array('Content-type: application/json')), json_encode($expected));
+  }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php
index 4ad1633..d523ec0 100644
--- a/core/modules/views/lib/Drupal/views/ViewExecutable.php
+++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php
@@ -1228,9 +1228,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();
@@ -1261,6 +1258,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_serialize_display_entity.yml b/core/modules/views/tests/views_test_config/config/views.view.test_serialize_display_entity.yml
new file mode 100644
index 0000000..f9a3836
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_serialize_display_entity.yml
@@ -0,0 +1,49 @@
+base_table: node
+name: test_serialize_display_entity
+description: ''
+tag: ''
+human_name: 'Test serialize 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: serialize
+      row:
+        type: data_entity
+      sorts:
+        created:
+          id: created
+          table: node
+          field: created
+          order: DESC
+      title: 'Test serialize'
+      arguments: {  }
+  data_1:
+    display_plugin: data
+    id: data_1
+    display_title: serialize
+    position: ''
+    display_options:
+      defaults:
+        access: false
+      path: test/serialize/entity
+base_field: nid
+disabled: '0'
+module: views
+langcode: und
diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_serialize_display_field.yml b/core/modules/views/tests/views_test_config/config/views.view.test_serialize_display_field.yml
new file mode 100644
index 0000000..a3214e5
--- /dev/null
+++ b/core/modules/views/tests/views_test_config/config/views.view.test_serialize_display_field.yml
@@ -0,0 +1,82 @@
+base_table: views_test_data
+name: test_serialize_display_field
+description: ''
+tag: ''
+human_name: 'Test serialize 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: serialize
+      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 serialize'
+      arguments: {  }
+  data_1:
+    display_plugin: data
+    id: data_1
+    display_title: serialize
+    position: ''
+    display_options:
+      defaults:
+        access: false
+        style: false
+        row: false
+      path: test/serialize/field
+      access:
+        type: none
+      style:
+        type: serialize
+      row:
+        type: data_field
+  data_2:
+    display_plugin: data
+    id: data_2
+    display_title: 'serialize - access denied'
+    position: ''
+    display_options:
+      defaults:
+        access: false
+        style: false
+        row: false
+      path: test/serialize/denied
+      access:
+        type: perm
+        options:
+          perm: 'administer views'
+      style:
+        type: serialize
+      row:
+        type: data_field
+base_field: id
+disabled: '0'
+module: views
+langcode: und
diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
index 853d5c9..ae362ff 100644
--- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
+++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
@@ -817,8 +817,14 @@ public function getFormBucket(ViewUI $view, $type, $display) {
 
     // Different types now have different rearrange forms, so we use this switch
     // to get the right one.
+    $rearrange_url = "admin/structure/views/nojs/rearrange/{$view->get('name')}/{$display['id']}/$type";
+    $rearrange_text = t('Rearrange');
+    $class = 'icon compact rearrange';
+
     switch ($type) {
       case 'filter':
+        // The rearrange form for filters contains the and/or UI, so override
+        // the used path.
         $rearrange_url = "admin/structure/views/nojs/rearrange-$type/{$view->get('name')}/{$display['id']}/$type";
         $rearrange_text = t('And/Or, Rearrange');
         // TODO: Add another class to have another symbol for filter rearrange.
@@ -836,6 +842,7 @@ public function getFormBucket(ViewUI $view, $type, $display) {
           );
           return $build;
         }
+        break;
       case 'header':
       case 'footer':
       case 'empty':
@@ -847,10 +854,7 @@ public function getFormBucket(ViewUI $view, $type, $display) {
           );
           return $build;
         }
-      default:
-        $rearrange_url = "admin/structure/views/nojs/rearrange/{$view->get('name')}/{$display['id']}/$type";
-        $rearrange_text = t('Rearrange');
-        $class = 'icon compact rearrange';
+        break;
     }
 
     // Create an array of actions to pass to theme_links
