Add a Controller function to make it easy to return json
If the serializer component is enabled it is used to generate the json data, if not the standard `json_encode` function is used
This commit is contained in:
parent
5c34ae4678
commit
f904a2ba99
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* Added `Controller::json` to simplify creating JSON responses when using the Serializer component
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@ -97,6 +98,29 @@ abstract class Controller implements ContainerAwareInterface
|
||||
return $this->redirect($this->generateUrl($route, $parameters), $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
|
||||
*
|
||||
* @param mixed $data The response data
|
||||
* @param int $status The status code to use for the Response
|
||||
* @param array $headers Array of extra headers to add
|
||||
* @param array $context Context to pass to serializer when using serializer component
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
protected function json($data, $status = 200, $headers = array(), $context = array())
|
||||
{
|
||||
if ($this->container->has('serializer')) {
|
||||
$json = $this->container->get('serializer')->serialize($data, 'json', array_merge(array(
|
||||
'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
|
||||
), $context));
|
||||
|
||||
return new JsonResponse($json, $status, $headers, true);
|
||||
}
|
||||
|
||||
return new JsonResponse($data, $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a flash message to the current session for type.
|
||||
*
|
||||
|
@ -14,12 +14,14 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
class ControllerTest extends TestCase
|
||||
{
|
||||
@ -124,6 +126,85 @@ class ControllerTest extends TestCase
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
public function testJson()
|
||||
{
|
||||
$container = $this->getMock(ContainerInterface::class);
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with('serializer')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$controller = new TestController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
$response = $controller->json(array());
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertEquals('[]', $response->getContent());
|
||||
}
|
||||
|
||||
public function testJsonWithSerializer()
|
||||
{
|
||||
$container = $this->getMock(ContainerInterface::class);
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with('serializer')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$serializer = $this->getMock(SerializerInterface::class);
|
||||
$serializer
|
||||
->expects($this->once())
|
||||
->method('serialize')
|
||||
->with(array(), 'json', array('json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS))
|
||||
->will($this->returnValue('[]'));
|
||||
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('serializer')
|
||||
->will($this->returnValue($serializer));
|
||||
|
||||
$controller = new TestController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
$response = $controller->json(array());
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertEquals('[]', $response->getContent());
|
||||
}
|
||||
|
||||
public function testJsonWithSerializerContextOverride()
|
||||
{
|
||||
$container = $this->getMock(ContainerInterface::class);
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('has')
|
||||
->with('serializer')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$serializer = $this->getMock(SerializerInterface::class);
|
||||
$serializer
|
||||
->expects($this->once())
|
||||
->method('serialize')
|
||||
->with(array(), 'json', array('json_encode_options' => 0, 'other' => 'context'))
|
||||
->will($this->returnValue('[]'));
|
||||
|
||||
$container
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('serializer')
|
||||
->will($this->returnValue($serializer));
|
||||
|
||||
$controller = new TestController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
$response = $controller->json(array(), 200, array(), array('json_encode_options' => 0, 'other' => 'context'));
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertEquals('[]', $response->getContent());
|
||||
$response->setEncodingOptions(JSON_FORCE_OBJECT);
|
||||
$this->assertEquals('{}', $response->getContent());
|
||||
}
|
||||
}
|
||||
|
||||
class TestController extends Controller
|
||||
@ -137,4 +218,9 @@ class TestController extends Controller
|
||||
{
|
||||
return parent::getUser();
|
||||
}
|
||||
|
||||
public function json($data, $status = 200, $headers = array(), $context = array())
|
||||
{
|
||||
return parent::json($data, $status, $headers, $context);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
"symfony/dependency-injection": "~2.8|~3.0",
|
||||
"symfony/config": "~2.8|~3.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~2.8|~3.0",
|
||||
"symfony/http-foundation": "~3.1",
|
||||
"symfony/http-kernel": "~2.8|~3.0",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/filesystem": "~2.8|~3.0",
|
||||
|
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* Added support for creating `JsonResponse` with a string of JSON data
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
|
@ -29,16 +29,19 @@ class JsonResponse extends Response
|
||||
|
||||
// Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML.
|
||||
// 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
|
||||
protected $encodingOptions = 15;
|
||||
const DEFAULT_ENCODING_OPTIONS = 15;
|
||||
|
||||
protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $data The response data
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param mixed $data The response data
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param bool $preEncoded If the data is already a JSON string
|
||||
*/
|
||||
public function __construct($data = null, $status = 200, $headers = array())
|
||||
public function __construct($data = null, $status = 200, $headers = array(), $preEncoded = false)
|
||||
{
|
||||
parent::__construct('', $status, $headers);
|
||||
|
||||
@ -46,7 +49,7 @@ class JsonResponse extends Response
|
||||
$data = new \ArrayObject();
|
||||
}
|
||||
|
||||
$this->setData($data);
|
||||
$this->setData($data, $preEncoded);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,34 +91,37 @@ class JsonResponse extends Response
|
||||
* Sets the data to be sent as JSON.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param bool $preEncoded If the data is already a JSON string
|
||||
*
|
||||
* @return JsonResponse
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setData($data = array())
|
||||
public function setData($data = array(), $preEncoded = false)
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
// HHVM does not trigger any warnings and let exceptions
|
||||
// thrown from a JsonSerializable object pass through.
|
||||
// If only PHP did the same...
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
} else {
|
||||
try {
|
||||
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
|
||||
// objects in a new exception that needs to be removed.
|
||||
// Fortunately, PHP 5.5 and up do not trigger any warning anymore.
|
||||
if (!$preEncoded) {
|
||||
if (defined('HHVM_VERSION')) {
|
||||
// HHVM does not trigger any warnings and let exceptions
|
||||
// thrown from a JsonSerializable object pass through.
|
||||
// If only PHP did the same...
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
} catch (\Exception $e) {
|
||||
if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
|
||||
throw $e->getPrevious() ?: $e;
|
||||
} else {
|
||||
try {
|
||||
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
|
||||
// objects in a new exception that needs to be removed.
|
||||
// Fortunately, PHP 5.5 and up do not trigger any warning anymore.
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
} catch (\Exception $e) {
|
||||
if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
|
||||
throw $e->getPrevious() ?: $e;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(json_last_error_msg());
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(json_last_error_msg());
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
|
@ -75,6 +75,18 @@ class JsonResponseTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type'));
|
||||
}
|
||||
|
||||
public function testConstructorWithPreEncoded()
|
||||
{
|
||||
$response = new JsonResponse('1', 200, array(), true);
|
||||
$this->assertEquals('1', $response->getContent());
|
||||
|
||||
$response = new JsonResponse('[1]', 200, array(), true);
|
||||
$this->assertEquals('[1]', $response->getContent());
|
||||
|
||||
$response = new JsonResponse('true', 200, array(), true);
|
||||
$this->assertEquals('true', $response->getContent());
|
||||
}
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
$response = JsonResponse::create(array('foo' => 'bar'), 204);
|
||||
|
Reference in New Issue
Block a user