Skip to content

Commit 423d76b

Browse files
committed
feature #17642 [FrameworkBundle] [DX] Add Controller::json method to make it easy to send json (mcfedr)
This PR was merged into the 3.1-dev branch. Discussion ---------- [FrameworkBundle] [DX] Add `Controller::json` method to make it easy to send json | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | Its currently a awkward to use Serializer component to send a `JsonResponse`. I have tried two approaches 1. use `Serializer::normalize` and `JsonResponse` 1. use `Serializer::serialize` and a plain `Response`, and set the `content-type` In either cases there is need for a custom `json` function so as not to repeat yourself and there are disadvantages. 1. In the first case you are only partly using `Serializer` and any custom `Encoder` would be skipped 1. In the second you are not making use of `JsonResponse`, particular disadvantage if you want to support JSONP. This new `json` method uses the serializer component is enabled it is used to generate the json data, and falls back to normal `JsonResponse` when its not. Commits ------- f904a2b Add a Controller function to make it easy to return json
2 parents cbb48eb + 6f5d497 commit 423d76b

File tree

4 files changed

+116
-1
lines changed

4 files changed

+116
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.1.0
5+
-----
6+
7+
* Added `Controller::json` to simplify creating JSON responses when using the Serializer component
8+
49
3.0.0
510
-----
611

Controller/Controller.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
1515
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
16+
use Symfony\Component\HttpFoundation\JsonResponse;
1617
use Symfony\Component\HttpFoundation\Response;
1718
use Symfony\Component\HttpFoundation\RedirectResponse;
1819
use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -97,6 +98,29 @@ protected function redirectToRoute($route, array $parameters = array(), $status
9798
return $this->redirect($this->generateUrl($route, $parameters), $status);
9899
}
99100

101+
/**
102+
* Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
103+
*
104+
* @param mixed $data The response data
105+
* @param int $status The status code to use for the Response
106+
* @param array $headers Array of extra headers to add
107+
* @param array $context Context to pass to serializer when using serializer component
108+
*
109+
* @return JsonResponse
110+
*/
111+
protected function json($data, $status = 200, $headers = array(), $context = array())
112+
{
113+
if ($this->container->has('serializer')) {
114+
$json = $this->container->get('serializer')->serialize($data, 'json', array_merge(array(
115+
'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
116+
), $context));
117+
118+
return new JsonResponse($json, $status, $headers, true);
119+
}
120+
121+
return new JsonResponse($data, $status, $headers);
122+
}
123+
100124
/**
101125
* Adds a flash message to the current session for type.
102126
*

Tests/Controller/ControllerTest.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
1515
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
1616
use Symfony\Component\DependencyInjection\ContainerInterface;
17+
use Symfony\Component\HttpFoundation\JsonResponse;
1718
use Symfony\Component\HttpFoundation\Request;
1819
use Symfony\Component\HttpFoundation\RequestStack;
1920
use Symfony\Component\HttpFoundation\Response;
2021
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
2122
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2223
use Symfony\Component\Security\Core\User\User;
24+
use Symfony\Component\Serializer\SerializerInterface;
2325

2426
class ControllerTest extends TestCase
2527
{
@@ -124,6 +126,85 @@ private function getContainerWithTokenStorage($token = null)
124126

125127
return $container;
126128
}
129+
130+
public function testJson()
131+
{
132+
$container = $this->getMock(ContainerInterface::class);
133+
$container
134+
->expects($this->once())
135+
->method('has')
136+
->with('serializer')
137+
->will($this->returnValue(false));
138+
139+
$controller = new TestController();
140+
$controller->setContainer($container);
141+
142+
$response = $controller->json(array());
143+
$this->assertInstanceOf(JsonResponse::class, $response);
144+
$this->assertEquals('[]', $response->getContent());
145+
}
146+
147+
public function testJsonWithSerializer()
148+
{
149+
$container = $this->getMock(ContainerInterface::class);
150+
$container
151+
->expects($this->once())
152+
->method('has')
153+
->with('serializer')
154+
->will($this->returnValue(true));
155+
156+
$serializer = $this->getMock(SerializerInterface::class);
157+
$serializer
158+
->expects($this->once())
159+
->method('serialize')
160+
->with(array(), 'json', array('json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS))
161+
->will($this->returnValue('[]'));
162+
163+
$container
164+
->expects($this->once())
165+
->method('get')
166+
->with('serializer')
167+
->will($this->returnValue($serializer));
168+
169+
$controller = new TestController();
170+
$controller->setContainer($container);
171+
172+
$response = $controller->json(array());
173+
$this->assertInstanceOf(JsonResponse::class, $response);
174+
$this->assertEquals('[]', $response->getContent());
175+
}
176+
177+
public function testJsonWithSerializerContextOverride()
178+
{
179+
$container = $this->getMock(ContainerInterface::class);
180+
$container
181+
->expects($this->once())
182+
->method('has')
183+
->with('serializer')
184+
->will($this->returnValue(true));
185+
186+
$serializer = $this->getMock(SerializerInterface::class);
187+
$serializer
188+
->expects($this->once())
189+
->method('serialize')
190+
->with(array(), 'json', array('json_encode_options' => 0, 'other' => 'context'))
191+
->will($this->returnValue('[]'));
192+
193+
$container
194+
->expects($this->once())
195+
->method('get')
196+
->with('serializer')
197+
->will($this->returnValue($serializer));
198+
199+
$controller = new TestController();
200+
$controller->setContainer($container);
201+
202+
$response = $controller->json(array(), 200, array(), array('json_encode_options' => 0, 'other' => 'context'));
203+
$this->assertInstanceOf(JsonResponse::class, $response);
204+
$this->assertEquals('[]', $response->getContent());
205+
$response->setEncodingOptions(JSON_FORCE_OBJECT);
206+
$this->assertEquals('{}', $response->getContent());
207+
}
127208
}
128209

129210
class TestController extends Controller
@@ -137,4 +218,9 @@ public function getUser()
137218
{
138219
return parent::getUser();
139220
}
221+
222+
public function json($data, $status = 200, $headers = array(), $context = array())
223+
{
224+
return parent::json($data, $status, $headers, $context);
225+
}
140226
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"symfony/dependency-injection": "~2.8|~3.0",
2323
"symfony/config": "~2.8|~3.0",
2424
"symfony/event-dispatcher": "~2.8|~3.0",
25-
"symfony/http-foundation": "~2.8|~3.0",
25+
"symfony/http-foundation": "~3.1",
2626
"symfony/http-kernel": "~2.8|~3.0",
2727
"symfony/polyfill-mbstring": "~1.0",
2828
"symfony/filesystem": "~2.8|~3.0",

0 commit comments

Comments
 (0)