diff --git a/lib/private/appframework/http/dispatcher.php b/lib/private/appframework/http/dispatcher.php
index 7f2717951a5643462f7528547db8dd7940d98b15..29a661d5743ed698f541cc9c3b53929e42a93593 100644
--- a/lib/private/appframework/http/dispatcher.php
+++ b/lib/private/appframework/http/dispatcher.php
@@ -30,6 +30,7 @@ use \OC\AppFramework\Utility\ControllerMethodReflector;
 
 use OCP\AppFramework\Controller;
 use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\DataResponse;
 use OCP\IRequest;
 
 
@@ -154,8 +155,8 @@ class Dispatcher {
 
 		$response = call_user_func_array(array($controller, $methodName), $arguments);
 
-		// format response if not of type response
-		if(!($response instanceof Response)) {
+		// format response
+		if($response instanceof DataResponse || !($response instanceof Response)) {
 
 			// get format from the url format or request format parameter
 			$format = $this->request->getParam('format');
diff --git a/lib/public/appframework/controller.php b/lib/public/appframework/controller.php
index b22eb73343ac8e45343556e391942d26e37995a1..398304e6febdbb4db805ad4f423463fd01b72191 100644
--- a/lib/public/appframework/controller.php
+++ b/lib/public/appframework/controller.php
@@ -29,6 +29,7 @@ namespace OCP\AppFramework;
 
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\DataResponse;
 use OCP\IRequest;
 
 
@@ -63,8 +64,17 @@ abstract class Controller {
 
 		// default responders
 		$this->responders = array(
-			'json' => function ($response) {
-				return new JSONResponse($response);
+			'json' => function ($data) {
+				if ($data instanceof DataResponse) {
+					$response = new JSONResponse(
+						$data->getData(),
+						$data->getStatus()
+					);
+					$response->setHeaders($data->getHeaders());
+					return $response;
+				} else {
+					return new JSONResponse($data);
+				}
 			}
 		);
 	}
diff --git a/lib/public/appframework/http/dataresponse.php b/lib/public/appframework/http/dataresponse.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c21de325e1141bb2ce8a7aa570de1d9694d9735
--- /dev/null
+++ b/lib/public/appframework/http/dataresponse.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2014 Bernhard Posselt <dev@bernhard-posselt.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\HTTP\DataResponse class
+ */
+
+namespace OCP\AppFramework\Http;
+
+use OCP\AppFramework\Http;
+
+/**
+ * A generic DataResponse class that is used to return generic data responses
+ * for responders to transform
+ */
+class DataResponse extends Response {
+
+	/**
+	 * response data
+	 * @var array|object
+	 */
+	protected $data;
+
+
+	/**
+	 * @param array|object $data the object or array that should be transformed
+	 * @param int $statusCode the Http status code, defaults to 200
+	 * @param array $headers additional key value based headers
+	 */
+	public function __construct($data=array(), $statusCode=Http::STATUS_OK,
+	                            array $headers=array()) {
+		$this->data = $data;
+		$this->setStatus($statusCode);
+		$this->setHeaders(array_merge($this->getHeaders(), $headers));
+	}
+
+
+	/**
+	 * Sets values in the data json array
+	 * @param array|object $data an array or object which will be transformed
+	 * @return DataResponse Reference to this object
+	 */
+	public function setData($data){
+		$this->data = $data;
+
+		return $this;
+	}
+
+
+	/**
+	 * Used to get the set parameters
+	 * @return array the data
+	 */
+	public function getData(){
+		return $this->data;
+	}
+
+
+}
diff --git a/lib/public/appframework/http/response.php b/lib/public/appframework/http/response.php
index 20e936bb86063f1cd685c00beb79778fcf44d910..354911fee2139900e7763e0098ca6c1b01885f99 100644
--- a/lib/public/appframework/http/response.php
+++ b/lib/public/appframework/http/response.php
@@ -93,7 +93,7 @@ class Response {
 	 */
 	public function addHeader($name, $value) {
 		$name = trim($name);  // always remove leading and trailing whitespace
-		                      // to be able to reliably check for security 
+		                      // to be able to reliably check for security
 		                      // headers
 
 		if(is_null($value)) {
@@ -106,6 +106,18 @@ class Response {
 	}
 
 
+	/**
+	 * Set the headers
+	 * @param array key value header pairs
+	 * @return Response Reference to this object
+	 */
+	public function setHeaders($headers) {
+		$this->headers = $headers;
+
+		return $this;
+	}
+
+
 	/**
 	 * Returns the set headers
 	 * @return array the headers
diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php
index e97ec548939d4b8307ef650fca78900230c0fdcc..0de94ff5b70e8b7cc49bf53ab0e0e254f4dd8e74 100644
--- a/tests/lib/appframework/controller/ControllerTest.php
+++ b/tests/lib/appframework/controller/ControllerTest.php
@@ -27,6 +27,7 @@ namespace OCP\AppFramework;
 use OC\AppFramework\Http\Request;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\DataResponse;
 
 
 class ChildController extends Controller {
@@ -45,6 +46,12 @@ class ChildController extends Controller {
 
 		return $in;
 	}
+
+	public function customDataResponse($in) {
+		$response = new DataResponse($in, 300);
+		$response->addHeader('test', 'something');
+		return $response;
+	}
 };
 
 class ControllerTest extends \PHPUnit_Framework_TestCase {
@@ -161,6 +168,21 @@ class ControllerTest extends \PHPUnit_Framework_TestCase {
 	}
 
 
+	public function testFormatDataResponseJSON() {
+		$expectedHeaders = array(
+			'test' => 'something',
+			'Cache-Control' => 'no-cache, must-revalidate'
+		);
+
+		$response = $this->controller->customDataResponse(array('hi'));
+		$response = $this->controller->buildResponse($response, 'json');
+
+		$this->assertEquals(array('hi'), $response->getData());
+		$this->assertEquals(300, $response->getStatus());
+		$this->assertEquals($expectedHeaders, $response->getHeaders());
+	}
+
+
 	public function testCustomFormatter() {
 		$response = $this->controller->custom('hi');
 		$response = $this->controller->buildResponse($response, 'json');
diff --git a/tests/lib/appframework/http/DataResponseTest.php b/tests/lib/appframework/http/DataResponseTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..961327c978c2b06ed92e7b1177257c47aa155018
--- /dev/null
+++ b/tests/lib/appframework/http/DataResponseTest.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2014 Bernhard Posselt <dev@bernhard-posselt.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Http;
+
+
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http;
+
+
+class DataResponseTest extends \PHPUnit_Framework_TestCase {
+
+	/**
+	 * @var DataResponse
+	 */
+	private $response;
+
+	protected function setUp() {
+		$this->response = new DataResponse();
+	}
+
+
+	public function testSetData() {
+		$params = array('hi', 'yo');
+		$this->response->setData($params);
+
+		$this->assertEquals(array('hi', 'yo'), $this->response->getData());
+	}
+
+
+	public function testConstructorAllowsToSetData() {
+		$data = array('hi');
+		$code = 300;
+		$response = new DataResponse($data, $code);
+
+		$this->assertEquals($data, $response->getData());
+		$this->assertEquals($code, $response->getStatus());
+	}
+
+
+	public function testConstructorAllowsToSetHeaders() {
+		$data = array('hi');
+		$code = 300;
+		$headers = array('test' => 'something');
+		$response = new DataResponse($data, $code, $headers);
+
+		$expectedHeaders = array('Cache-Control' => 'no-cache, must-revalidate');
+		$expectedHeaders = array_merge($expectedHeaders, $headers);
+
+		$this->assertEquals($data, $response->getData());
+		$this->assertEquals($code, $response->getStatus());
+		$this->assertEquals($expectedHeaders, $response->getHeaders());
+	}
+
+
+	public function testChainability() {
+		$params = array('hi', 'yo');
+		$this->response->setData($params)
+			->setStatus(Http::STATUS_NOT_FOUND);
+
+		$this->assertEquals(Http::STATUS_NOT_FOUND, $this->response->getStatus());
+		$this->assertEquals(array('hi', 'yo'), $this->response->getData());
+	}
+
+
+}
diff --git a/tests/lib/appframework/http/DispatcherTest.php b/tests/lib/appframework/http/DispatcherTest.php
index 9d5ec09a293c3f6a03c2b80386b4e2fddfd016a3..f082ddc8b3a068efd06b09c9c91fc98717e518fe 100644
--- a/tests/lib/appframework/http/DispatcherTest.php
+++ b/tests/lib/appframework/http/DispatcherTest.php
@@ -28,6 +28,7 @@ use OC\AppFramework\Middleware\MiddlewareDispatcher;
 use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\DataResponse;
 use OCP\AppFramework\Controller;
 
 
@@ -46,6 +47,18 @@ class TestController extends Controller {
 		});
 		return array($int, $bool, $test, $test2);
 	}
+
+
+	/**
+	 * @param int $int
+	 * @param bool $bool
+	 */
+	public function execDataResponse($int, $bool, $test=4, $test2=1) {
+		return new DataResponse(array(
+			'text' => array($int, $bool, $test, $test2)
+		));
+	}
+
 }
 
 
@@ -84,7 +97,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$this->controller = $this->getMock(
 			'\OCP\AppFramework\Controller',
 			array($this->controllerMethod), array($app, $request));
-		
+
 		$this->request = $this->getMockBuilder(
 			'\OC\AppFramework\Http\Request')
 			->disableOriginalConstructor()
@@ -96,7 +109,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 			$this->http, $this->middlewareDispatcher, $this->reflector,
 			$this->request
 		);
-		
+
 		$this->response = $this->getMockBuilder(
 			'\OCP\AppFramework\Http\Response')
 			->disableOriginalConstructor()
@@ -111,7 +124,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 	 * @param string $out
 	 * @param string $httpHeaders
 	 */
-	private function setMiddlewareExpectations($out=null, 
+	private function setMiddlewareExpectations($out=null,
 		$httpHeaders=null, $responseHeaders=array(),
 		$ex=false, $catchEx=true) {
 
@@ -119,20 +132,20 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 			$exception = new \Exception();
 			$this->middlewareDispatcher->expects($this->once())
 				->method('beforeController')
-				->with($this->equalTo($this->controller), 
+				->with($this->equalTo($this->controller),
 					$this->equalTo($this->controllerMethod))
 				->will($this->throwException($exception));
 			if($catchEx) {
 				$this->middlewareDispatcher->expects($this->once())
 					->method('afterException')
-					->with($this->equalTo($this->controller), 
+					->with($this->equalTo($this->controller),
 						$this->equalTo($this->controllerMethod),
 						$this->equalTo($exception))
 					->will($this->returnValue($this->response));
 			} else {
 				$this->middlewareDispatcher->expects($this->once())
 					->method('afterException')
-					->with($this->equalTo($this->controller), 
+					->with($this->equalTo($this->controller),
 						$this->equalTo($this->controllerMethod),
 						$this->equalTo($exception))
 					->will($this->returnValue(null));
@@ -141,7 +154,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		} else {
 			$this->middlewareDispatcher->expects($this->once())
 				->method('beforeController')
-				->with($this->equalTo($this->controller), 
+				->with($this->equalTo($this->controller),
 					$this->equalTo($this->controllerMethod));
 			$this->controller->expects($this->once())
 				->method($this->controllerMethod)
@@ -165,38 +178,38 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 			->will($this->returnValue($responseHeaders));
 		$this->http->expects($this->once())
 			->method('getStatusHeader')
-			->with($this->equalTo(Http::STATUS_OK), 
+			->with($this->equalTo(Http::STATUS_OK),
 				$this->equalTo($this->lastModified),
 				$this->equalTo($this->etag))
 			->will($this->returnValue($httpHeaders));
-		
+
 		$this->middlewareDispatcher->expects($this->once())
 			->method('afterController')
-			->with($this->equalTo($this->controller), 
+			->with($this->equalTo($this->controller),
 				$this->equalTo($this->controllerMethod),
 				$this->equalTo($this->response))
 			->will($this->returnValue($this->response));
 
 		$this->middlewareDispatcher->expects($this->once())
 			->method('afterController')
-			->with($this->equalTo($this->controller), 
+			->with($this->equalTo($this->controller),
 				$this->equalTo($this->controllerMethod),
 				$this->equalTo($this->response))
 			->will($this->returnValue($this->response));
 
 		$this->middlewareDispatcher->expects($this->once())
 			->method('beforeOutput')
-			->with($this->equalTo($this->controller), 
+			->with($this->equalTo($this->controller),
 				$this->equalTo($this->controllerMethod),
 				$this->equalTo($out))
-			->will($this->returnValue($out));		
+			->will($this->returnValue($out));
 	}
 
 
 	public function testDispatcherReturnsArrayWith2Entries() {
 		$this->setMiddlewareExpectations();
 
-		$response = $this->dispatcher->dispatch($this->controller, 
+		$response = $this->dispatcher->dispatch($this->controller,
 			$this->controllerMethod);
 		$this->assertNull($response[0]);
 		$this->assertEquals(array(), $response[1]);
@@ -210,7 +223,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$responseHeaders = array('hell' => 'yeah');
 		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders);
 
-		$response = $this->dispatcher->dispatch($this->controller, 
+		$response = $this->dispatcher->dispatch($this->controller,
 			$this->controllerMethod);
 
 		$this->assertEquals($httpHeaders, $response[0]);
@@ -227,9 +240,9 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$out = 'yo';
 		$httpHeaders = 'Http';
 		$responseHeaders = array('hell' => 'yeah');
-		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true);		
+		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true);
 
-		$response = $this->dispatcher->dispatch($this->controller, 
+		$response = $this->dispatcher->dispatch($this->controller,
 			$this->controllerMethod);
 
 		$this->assertEquals($httpHeaders, $response[0]);
@@ -249,7 +262,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true, false);
 
 		$this->setExpectedException('\Exception');
-		$response = $this->dispatcher->dispatch($this->controller, 
+		$response = $this->dispatcher->dispatch($this->controller,
 			$this->controllerMethod);
 
 	}
@@ -342,6 +355,31 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 	}
 
 
+	public function testResponseTransformsDataResponse() {
+		$this->request = new Request(array(
+			'post' => array(
+				'int' => '3',
+				'bool' => 'false'
+			),
+			'urlParams' => array(
+				'format' => 'json'
+			),
+			'method' => 'GET'
+		));
+		$this->dispatcher = new Dispatcher(
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
+		$controller = new TestController('app', $this->request);
+
+		// reflector is supposed to be called once
+		$this->dispatcherPassthrough();
+		$response = $this->dispatcher->dispatch($controller, 'execDataResponse');
+
+		$this->assertEquals('{"text":[3,false,4,1]}', $response[2]);
+	}
+
+
 	public function testResponseTransformedByAcceptHeader() {
 		$this->request = new Request(array(
 			'post' => array(
diff --git a/tests/lib/appframework/http/ResponseTest.php b/tests/lib/appframework/http/ResponseTest.php
index e83fe9e2d8487d1f9e4dee3c20b2bcfb23467a7e..b1dddd9ebc7a6dc4a46dd4c3c6557bbcbabc1c93 100644
--- a/tests/lib/appframework/http/ResponseTest.php
+++ b/tests/lib/appframework/http/ResponseTest.php
@@ -48,10 +48,24 @@ class ResponseTest extends \PHPUnit_Framework_TestCase {
 	}
 
 
+	function testSetHeaders(){
+		$expected = array(
+			'Last-Modified' => 1,
+			'ETag' => 3,
+			'Something-Else' => 'hi'
+		);
+
+		$this->childResponse->setHeaders($expected);
+		$headers = $this->childResponse->getHeaders();
+
+		$this->assertEquals($expected, $headers);
+	}
+
+
 	public function testAddHeaderValueNullDeletesIt(){
 		$this->childResponse->addHeader('hello', 'world');
 		$this->childResponse->addHeader('hello', null);
-		$this->assertEquals(1, count($this->childResponse->getHeaders()));	
+		$this->assertEquals(1, count($this->childResponse->getHeaders()));
 	}
 
 
@@ -93,18 +107,18 @@ class ResponseTest extends \PHPUnit_Framework_TestCase {
 
 	public function testCacheSecondsZero() {
 		$this->childResponse->cacheFor(0);
-		
+
 		$headers = $this->childResponse->getHeaders();
-		$this->assertEquals('no-cache, must-revalidate', $headers['Cache-Control']);	
+		$this->assertEquals('no-cache, must-revalidate', $headers['Cache-Control']);
 	}
 
 
 	public function testCacheSeconds() {
 		$this->childResponse->cacheFor(33);
-		
+
 		$headers = $this->childResponse->getHeaders();
-		$this->assertEquals('max-age=33, must-revalidate', 
-			$headers['Cache-Control']);	
+		$this->assertEquals('max-age=33, must-revalidate',
+			$headers['Cache-Control']);
 	}