I have read the RequestHandler
part in cookbook. There are isXml()
, isRss()
, etc. But there's no isJson()
.
Any other way to check whether a request is JSON?
So when the url is mysite.com/products/view/1.json
it will give JSON data, but without .json
it will give the HTML View.
Thanks
I dont think cakePHP has some function like isJson() for json data, you could create your custom though, like:
//may be in your app controller
function isJson($data) {
return (json_decode($data) != NULL) ? true : false;
}
//and you can use it in your controller
if( $this->isJson($your_request_data) ) {
...
}
Added: if you want to check .json extension and process accordingly, then you could do in your controller:
$this->request->params['ext']; //which would give you 'json' if you have .json extension
CakePHP is handling this correctly, because JSON is a response type and not a type of request. The terms request and response might be causing some confusing. The request object represents the header information of the HTTP request sent to the server. A browser usually sends POST or GET requests to a server, and those requests can not be formatted as JSON. So it's not possible for a request to be of type JSON.
With that said, the server can give a response of JSON and a browser can put in the request header that it supports a JSON response. So rather than check what the request was. Check what accepted responses are supported by the browser.
So instead of writing $this->request->isJson()
you should write $this->request->accepts('application/json')
.
This information is ambiguously shown in the document here, but there is no reference see also
links in the is(..)
documentation. So many people look there first. Don't see JSON and assume something is missing.
If you want to use a request detector to check if the browser supports a JSON response, then you can easily add a one liner in your beforeFilter.
$this->request->addDetector('json',array('callback'=>function($req){return $req->accepts('application/json');}));
There is a risk associated with this approach, because a browser can send multiple response types as a possible response from the server. Including a wildcard for all types. So this limits you to only requests that indicate a JSON response is supported. Since JSON is a text format a type of text/plain
is a valid response type for a browser expecting JSON.
We could modify our rule to include text/plain
for JSON responses like this.
$this->request->addDetector('json',array('callback'=>function($req){
return $req->accepts('application/json') || $req->accepts('text/plain');
}));
That would include text/plain requests as a JSON response type, but now we have a problem. Just because the browser supports a text/plain response doesn't mean it's expecting a JSON response.
This is why it's better to incorporate a naming convention into your URL to indicate a JSON response. You can use a .json
file extension or a /json/controller/action
prefix.
I prefer to use a named prefix for URLs. That allows you to create json_action
methods in your controller. You can then create a detector for the prefix like this.
$this->request->addDetector('json',array('callback'=>function($req){return isset($req->params['prefix']) && $req->params['prefix'] == 'json';}));
Now that detector will always work correctly, but I argue it's an incorrect usage of detecting a JSON request. Since there is no such thing as a JSON request. Only JSON responses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With