How to configure Symfony JsonResponse output? - json

Is there any way to configure JsonResponse output to be - for example - unescaped unicode?
something like the output of this php function:
json_encode($array, JSON_UNESCAPED_UNICODE);

Yes, here you go:
$response = new JsonResponse($data);
$response->setEncodingOptions(JSON_UNESCAPED_UNICODE);
return $response;

To do this globally, make an event listener. Something like this:
services.yml:
event_listeners.json_formatter_listener:
class: EventListeners\JsonResponseFormatterListener
tags:
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
JsonResponseFormatterListener.php:
<?php
namespace EventListeners;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class JsonResponseFormatterListener
{
public function onKernelResponse(FilterResponseEvent $event)
{
$response = $event->getResponse();
if ($response instanceof JsonResponse) {
$response->setEncodingOptions(JSON_UNESCAPED_UNICODE);
}
}
}

Related

How to retrieve data from MySQL to JSON?

I have a Symfony project where I want to store the all the rows from my MySQL table to JSON. Currently there are five rows in my table, but in my browser it only returns five empty values as {"results":[{},{},{},{},{}]}
I guess I have done something right, but not everything. What am I missing in my code?
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$results = $repository->findAll();
return $this->json(['results' => $results]);
}
Try createQueryBuilder its usefull.
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository)
{
$qb = $repository->createQueryBuilder("b");
$results = $qb->getQuery()->getArrayResult();
return $this->json(['results' => $results]);
}
You can use the serializer or re-create the array yourself like that
$courses = $doctrine->getRepository(Course::class)->findByLikeTitle($search, $userId);
foreach ($courses as $key => $course) {
$jsonCourses[$key]['title'] = $course->getTitle();
}
```
You can achieve this by Using a Serializer to convert the array of objects into JSON. There are other ways to achieve this like using jsonResponse for example. But the serializer is the most robust way imo.
Example only:
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/budget/api', name: 'budget-api')]
public function index(Request $request, BudgetRepository $repository, SerializerInterface $serializer)
{
$results = $repository->findAll();
$jsonResults = $serializer->serialize($results, 'json');
//If you need to handle any circular references, you can use this..
$jsonResults = $serializer->serialize($results, 'json', array(
'circular_reference_handler' => function ($object) { return $object; },
));
return $jsonResults;
}

Passing the data of database in json object in laravel

Well, here is what I did:
public function api_index()
{
$agents=DB::table('users')
->select('id','username','role')
->get();
return response()->json($agents);
}
And its throwing this in browser:
[{"id":"1","username":"suzan","role":"Admin"}, {"id":"2","username":"momta","role":"admin"}]
but i actually needed is i need a json object and on that json object i need these data. may be like this:
{"jsonboject":[{"id":"1","username":"suzan","role":"Admin"},{"id":"2","username":"momta","role":"admin"}]}
How can i do this?
Try this
public function api_index()
{
$agents=DB::table('users')
->select('id','username','role')
->get();
return response(['jsonboject' => $agents]);
}
Do this:
return response()->json(['jsonobject' => $agents]);
Do the following code :
public function api_index()
{
$agents=DB::table('users')
->select('id','username','role')
->get();
return response()->json(array('jsonobject'=>$agents),200);
}

In Symfony2, is there a way to pretty-print JSON responses?

I am writing a REST API in Symfony2, and I have my controller outputting JSON responses using the provided JsonResponse class:
$response = new JsonResponse(null, $status);
$response->setData($node['Content']);
return $response;
However, for debugging purposes, it would be nice to be able to pretty print the output. Is there an argument I can pass to the JsonResponse object to enable pretty-printing of the output?
Creating an event listener for that, as in Pawel's answer is overengineering.
To prettify, you just pass in the JSON_PRETTY_PRINT constant to the JsonResponse via the setEncodingOptions, like in this example:
$response = new JsonResponse( [ 'your' => 'data' ] );
$response->setEncodingOptions( $response->getEncodingOptions() | JSON_PRETTY_PRINT );
return $response;
You can see the Symfony API for more information:
Class JsonResponse:
http://api.symfony.com/3.2/Symfony/Component/HttpFoundation/JsonResponse.html
Method setEncodingOptions:
http://api.symfony.com/3.2/Symfony/Component/HttpFoundation/JsonResponse.html#method_setEncodingOptions
This is documentation for v3.2... but older versions like for example v2.7 also have this method.
You can create EventListener for that. Here is mine
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Preetify json response.
*/
class FormatJsonResponseListener
{
public function onResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$request = $event->getRequest();
if (APPLICATION_ENV === 'development' || APPLICATION_ENV === 'dev' || $request->query->get('pretty_json', false) == true) {
$response = $event->getResponse();
$responseData = $event->getResponse()->getContent();
$response->setContent(Json::indent($responseData));
$event->setResponse($response);
}
}
}
And register that service with:
#services.ym
services:
your.service.listener.format_json:
class: Your\Vendor\FormatJsonResponseListener
tags:
- { name: kernel.event_listener, event: kernel.response, method: onResponse }
My JSON class is here: https://github.com/sourcefabric/Newscoop/blob/master/newscoop/library/Newscoop/Gimme/Json.php
Instead APPLICATION_ENV you can pass to listener parameter kernel.debug.
You can also modify response with (PHP >= 5.4.0, HttpFoundation >= 2.5)
$response->setEncodingOptions($response->getEncodingOptions() | JSON_PRETTY_PRINT);

laravel validate Content-Type: application/json request

in laravel 5 i made a new request named ApiRequest.
class ApiRequest extends Request
{
public function authorize() {
return $this->isJson();
}
public function rules()
{
return [
//
];
}
}
As you can see i am accepting only json data. And i am receiving the json in controller like this
public function postDoitApi(ApiRequest $payload) {
$inputJson = json_decode($payload->getContent());
$name = $inputJson->name;
}
Which is working fine. I am getting data in $name. But now i need to validate the input json.
I need to set validation rule in ApiRequest for the name key like this
public function rules()
{
return [
'name' => 'required|min:6'
];
}
Help me to do this. Thanks.
Laravel validates AJAX requests the same way. Just make sure you're setting one of these request headers on your request:
'Accept': 'application/json'
'X-Requested-With': 'XMLHttpRequest'
Validating any headers can be done in clean way two steps:
Step 1: Prepare header data to request data in prepareForValidation method.
public function prepareForValidation()
{
$this->merge([
"content_type" => $this->headers->get("Content-type"),
]);
}
Step 2: Apply any validation rules that you want, (Here, you want your data exact to be application/json. so
public function rules(): array
{
return [
"content_type" => "required|in:application/json",
];
}
Complete Example looks like:
/**
* Class LoginRequest
*
* #package App\Requests
*/
class LoginRequest extends FormRequest
{
public function prepareForValidation()
{
$this->merge([
"content_type" => $this->headers->get("Content-type"),
]);
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
return [
"content_type" => "required|in:application/json",
];
}
}
You could use a validator method instead of rules method:
class ApiRequest extends Request
{
public function authorize() {
return $this->isJson();
}
public function validator(){
//$data = \Request::instance()->getContent();
$data = json_decode($this->instance()->getContent());
return \Validator::make($data, [
'name' => 'required|min:6'
], $this->messages(), $this->attributes());
}
//what happens if validation fails
public function validate(){
$instance = $this->getValidatorInstance();
if($this->passesAuthorization()){
$this->failedAuthorization();
}elseif(!$instance->passes()){
$this->failedValidation($instance);
}elseif( $instance->passes()){
if($this->ajax())
throw new HttpResponseException(response()->json(['success' => true]));
}
}
}
return $inputJson->toArray();
and then pass to validator
$name = ['name'=>'er'];
$rules = array('name' => 'required|min:4');
$validation = Validator::make($name,$rules);
you can put following function in your ApiRequest form request.
public function validator(){
return \Validator::make(json_decode($this->getContent(),true), $this->rules(), $this->messages(), $this->attributes());
}

How to force convert json action in Cakephp Rest

i need force convert json action in cakephp rest response. When i set '_serialize' like this
$this->set(array('message' => $lessons, '_serialize' => array('message')));
it works but some turkish characters view in unicode like "\u00e7al\u0131\u015fma alan\u0131".
It's solution is render data with json_encode($data, JSON_UNESCAPED_UNICODE) but cakephp render it automatically. How to force json_encode with JSON_UNESCAPED_UNICODE ?
Sorry for bad English.
in cakePHP 3 you can say in controller:
$this->set('_jsonOptions', JSON_UNESCAPED_UNICODE);
$this->set('_serialize', ['zones']);
which will override the options used.
JsonView doesn't accept options
There's no way to inject options in the json_encode() call invoked by JsonView, as it's hard coded optionless in the _serialize() method like this:
protected function _serialize($serialize) {
// ...
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT);
}
return json_encode($data);
}
Use a custom/extended view
So if you want to use automatic serialization, then you have to create your own/an extended view that either accepts options, or hard codes your desired options.
Here's an (untested) example with hard coded options. The _serialize() method is basically just a copy with the JSON_UNESCAPED_UNICODE option added:
App::uses('JsonView', 'View');
class MyJsonView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
See also http://book.cakephp.org/2.0/en/views.html#creating-your-own-view-classes
I haven't tested this myself, so it's just from the top of my head.
You could write your own View class extending JsonView and override the _serialize method.
https://github.com/cakephp/cakephp/blob/4e8e266754a25748f481b2f567e45f767808be53/lib/Cake/View/JsonView.php#L131
<?php
App::uses('JsonView', 'View');
class MyCustomView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
And then in your controller do something like
<?php
App::uses('MyCustomView', 'View');
class SomeController extends AppController {
public function someMethod() {
$this->viewClass = 'MyCustomView';
// What ever you normally do
}
}