My server side code returns a value which is a JSON object on success and a string 'false' on failure. Now how can I check whether the returned value is a JSON object?
The chosen solution doesn't actually work for me because I get a
"Unexpected Token <"
error in Chrome. This is because the error is thrown as soon as the parse comes across and unknown character. However, there is a way around this if you are returning only string values through ajax (which can be fairly useful if you are using PHP or ASPX to process ajax requests and might or might not return JSON depending on conditions)
The solution is quite simple, you can do the following to check if it was a valid JSON return
var IS_JSON = true;
try
{
var json = $.parseJSON(msg);
}
catch(err)
{
IS_JSON = false;
}
As I have said before, this is the solution for if you are either returning string type stuff from your AJAX request or if you are returning mixed type.
jQuery.parseJSON() should return an object of type "object", if the string was JSON, so you only have to check the type with typeof
var response=jQuery.parseJSON('response from server');
if(typeof response =='object')
{
// It is JSON
}
else
{
if(response ===false)
{
// the response was a string "false", parseJSON will convert it to boolean false
}
else
{
// the response was something else
}
}
Solution 3 (fastest way)
/**
* #param Object
* #returns boolean
*/
function isJSON (something) {
if (typeof something != 'string')
something = JSON.stringify(something);
try {
JSON.parse(something);
return true;
} catch (e) {
return false;
}
}
You can use it:
var myJson = [{"user":"chofoteddy"}, {"user":"bart"}];
isJSON(myJson); // true
The best way to validate that an object is of type JSON or array is as follows:
var a = [],
o = {};
Solution 1
toString.call(o) === '[object Object]'; // true
toString.call(a) === '[object Array]'; // true
Solution 2
a.constructor.name === 'Array'; // true
o.constructor.name === 'Object'; // true
But, strictly speaking, an array is part of a JSON syntax. Therefore, the following two examples are part of a JSON response:
console.log(response); // {"message": "success"}
console.log(response); // {"user": "bart", "id":3}
And:
console.log(response); // [{"user":"chofoteddy"}, {"user":"bart"}]
console.log(response); // ["chofoteddy", "bart"]
AJAX / JQuery (recommended)
If you use JQuery to bring information via AJAX. I recommend you put in the "dataType" attribute the "json" value, that way if you get a JSON or not, JQuery validate it for you and make it known through their functions "success" and "error". Example:
$.ajax({
url: 'http://www.something.com',
data: $('#formId').serialize(),
method: 'POST',
dataType: 'json',
// "sucess" will be executed only if the response status is 200 and get a JSON
success: function (json) {},
// "error" will run but receive state 200, but if you miss the JSON syntax
error: function (xhr) {}
});
If you have jQuery, use isPlainObject.
if ($.isPlainObject(my_var)) {}
var checkJSON = function(m) {
if (typeof m == 'object') {
try{ m = JSON.stringify(m); }
catch(err) { return false; } }
if (typeof m == 'string') {
try{ m = JSON.parse(m); }
catch (err) { return false; } }
if (typeof m != 'object') { return false; }
return true;
};
checkJSON(JSON.parse('{}')); //true
checkJSON(JSON.parse('{"a":0}')); //true
checkJSON('{}'); //true
checkJSON('{"a":0}'); //true
checkJSON('x'); //false
checkJSON(''); //false
checkJSON(); //false
Since it's just false and json object, why don't you check whether it's false, otherwise it must be json.
if(ret == false || ret == "false") {
// json
}
I know this thread has been answered already, but coming here didn't really solve my problems, I found this function somewhere else.
maybe someone coming here will find it to be of some use to them;
function getClass(obj) {
if (typeof obj === "undefined")
return "undefined";
if (obj === null)
return "null";
return Object.prototype.toString.call(obj)
.match(/^\[object\s(.*)\]$/)[1];
}
var data = 'json string ?';
var jdata = null;
try
{
jdata = $.parseJSON(data);
}catch(e)
{}
if(jdata)
{
//use jdata
}else
{
//use data
}
If you want to test explicitly for valid JSON (as opposed to the absence of the returned value false), then you can use a parsing approach as described here.
I don't really like the accepted answer. First and foremost it requires jQuery, which is not always available or required. Secondly, it does a full stringification of the object which to me is overkill. Here's a simple function that thoroughly detects whether a value is JSON-like, using nothing more than a few parts of the lodash library for genericity.
import * as isNull from 'lodash/isNull'
import * as isPlainObject from 'lodash/isPlainObject'
import * as isNumber from 'lodash/isNumber'
import * as isBoolean from 'lodash/isBoolean'
import * as isString from 'lodash/isString'
import * as isArray from 'lodash/isArray'
function isJSON(val) {
if (isNull(val)
|| isBoolean(val)
|| isString(val))
return true;
if (isNumber(val))
return !isNaN(val) && isFinite(val)
if (isArray(val))
return Array.prototype.every.call(val, isJSON)
if (isPlainObject(val)) {
for (const key of Object.keys(val)) {
if (!isJSON(val[key]))
return false
}
return true
}
return false
}
I've even taken the time to put it up in npm as a package: https://npmjs.com/package/is-json-object. Use it together with something like Webpack to get it in the browser.
Hope this helps someone!
I am using this to validate JSON Object
function isJsonObject(obj) {
try {
JSON.parse(JSON.stringify(obj));
} catch (e) {
return false;
}
return true;
}
I am using this to validate JSON String
function isJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
i tried all of the suggested answers, nothing worked for me, so i had to use
jQuery.isEmptyObject()
hoe that helps someone else out with this issue
You should return json always, but change its status, or in following example the ResponseCode property:
if(callbackResults.ResponseCode!="200"){
/* Some error, you can add a message too */
} else {
/* All fine, proceed with code */
};
Related
I was looking at this question: Return true/false to javascript from php file
But is not what I'm looking for, as I don't need to return text/strings in JSON.
What I want is to return true or false statements from loaded php file to jQuery.
jQuery: (How I think it could work)
if($("#lvlupann").load("/templ/checknlvl.php") == true){
$("#lvlupann").addClass("nlvlann");
}
And the mighty php file : (checknlvl.php)
if(1 == 1){
return true;
}
But obviously it doesn't return true/false, and class is not added... I know I'm going probably wrong on it, but don't know what to overwrite...
Any help would be appreciated.
You are doing it wrong.
The .load() method is asynchronous and does not return the value from the server (it returns the element that it was called on: $("#lvlupann")), so using the returned value in an if statement does not make sense.
You have to wait for the request to finish before you can use the value, like so:
$("#lvlupann").load("/templ/checknlvl.php", function (value) {
if (value == true) {
$("#lvlupann").addClass("nlvlann");
}
});
As for the PHP file, the return true; will just stop the script. It does not send anything to the client. In order to send two or more things from PHP to the client you need to package the output in some fashion.
The $.get method would be useful:
$.get('/templ/checknlvl.php').done(function (data) {
$("#lvlupann").html(data.content);
if (data.success) {
$("#lvlupann").addClass("nlvlann");
}
});
<?php
echo json_encode([
'content' => '<strong>Some content...</strong>',
'success' => true,
]);
die;
If all you want to do is get a boolean value from the PHP script then something like this would do it:
$.get('/templ/checknlvl.php').done(function (value) {
if (value === "true") {
$("#lvlupann").addClass("nlvlann");
}
});
<?php
if (1 == 1) {
echo 'true';
} else {
echo 'false';
}
die;
I'm facing a strange problem for the last 10 hours and its really very annoying. The problem is with jquery printing json data from php. The php script is running fine, but when the ajax call returns in complete: event i'm not getting any valid otput.
here is the jquery code::
list_choice = "A";
content_choice = "Artists"; //globals to store default value
$(document).ready(function() {
$('.list-nav > a').click(function() {
var ltext = $(this).text();
list_choice = ltext;
console.log(ltext+" <------> ");
$.ajax({
url: 'retrieveFileFront.php',
data: {type: content_choice, navtext: list_choice},
type: 'POST',
dataType: 'json',
complete: function(data) {
console.log(data['message']['Album_Name']);
}
});
return false;
});
});
i had to use complete: event as success: didn't worked at all. Atleast i'm getting some sort of output from the complete: event, although its giving undefined or [object][Object] which is totally ridiculous.
here is the retrieveFileFront.php:
<?php
require './retrieveFiles.php';
$type = $_POST['type'];
$nav_text = $_POST['navtext'];
$ret_files = new retrieveFiles($type, $nav_text);
$data = $ret_files->retFiles();
if ($data['success'] == FALSE) {
$data = array('success' => FALSE, 'message' => 'Sorry an Error has occured');
echo json_encode($data);
} else {
echo json_encode($data);
}
?>
and here is the /retrieveFiles.php
<?php
class retrieveFiles {
public $content_type;
public $list_nav;
public $connection;
public $result;
public $result_obj;
public $tags_array;
public $query;
public $row;
public function __construct($type, $nav_text) {
$this->content_type = $type;
$this->list_nav = $nav_text;
}
public function retFiles() {
#$this->connection = new mysqli('localhost', 'usr', 'pass', 'data');
if(!$this->connection) {
die("Sorry Database connection could not be made please try again later. Sorry for the inconvenience..");
}
if ($this->content_type == "Artists") {
$this->query = "SELECT album_name, album_art FROM album_dummy NATURAL JOIN album_images_dummy WHERE artist_name LIKE '$this->list_nav%'";
try {
$this->result = $this->connection->query($this->query);
$this->row = $this->result->fetch_row();
if (isset($this->row[0]) && isset($this->row[1])) {
$this->tags_array = array("success" => true, "message" => array("Album_Name" => $this->row[0], "Album_Art" => $this->row[1]));
return $this->tags_array;
}
} catch (Exception $e) {
echo 'Sorry an Error has occurred'.$e;
return false;
}
}
}
}
?>
I'm getting a 200 response in console in firebug, which indicates that its running okay.
<!DOCTYPE HTML>
{"success":true,"message":{"Album_Name":"Streetcleaner","Album_Art":"\/var\/www\/html\/MusicLibrary\/Musics\/1989 - Streetcleaner\/folder.jpg"}}
Now this is making me even more confused as i can see that the json is formatted properly. Please provide any sort of suggestion on how to solve this problem.
Thanks in advance..
JSON encoded data is usually not sent like
data['message']['Album_Name']);
But rather like:
data.message.Album_Name;
You're calling your results the wrong way. These are not associative arrays anymore but are now objects, as the name JSON (JavaScript Object Notation) suggests.
You need to parse the json response using
data = $.parseJSON(data)
Use success event instead of complete in ajax and we can able to parse JSON encoded data in javascript/jQuery by using JSON.parse
well after a long period of trauma, i finally found a solution, turns out that i needed to parse the response text and then access the objects, individually.
Here is the working code
list_choice = "A";
content_choice = "Artists"; //globals to store default value
$(document).ready(function() {
$('.list-nav > a').click(function() {
var ltext = $(this).text();
list_choice = ltext;
console.log(ltext+" <------> ");
$('#loading').css('visibility', 'visible');
$.ajax({
url: 'retrieveFileFront.php',
data: {type: content_choice, navtext: list_choice},
type: 'POST'
dataType: 'json',
complete: function(data) {
var res = data.responseText;
res = res.replace(/<!DOCTYPE HTML>/g, "");
res = res.trim();
console.log(res);
var arr = JSON.parse("[" + res +"]"); //needed to parse JSON object into arrays
console.log(arr[0].message.Album_Name);
console.log(arr[0].message.Album_Art);
$('#loading').css('visibility','hidden');
}
});
return false;
});
This works fine and gives the desired response. Anyways thanks for the help, guys.
NOTE: I've pasted more code than just the ajax calls, on the off chance that code is (part of) what's causing the problem. I don't think it is, however, so you're probably better off focussing on the ajax and jAjax functions a bit further down. Also note that, since there's a comment (with upvote) on this question saying my code is hard to decipher, I'd happily clarify what needs clarifying if that could prove to be the key in finding the problem. Thanks.
Here's the thing. I'm trying to ditch jQuery, since the only thing I use is the $.ajax() method, and including an entire lib like jQuery for just 1 feature is IMO crazy. I don't even need the full functionality of the $.ajax method anyway, hence I wrote my own ajax function.
The problem is: it's not working, and I can't seem to figure out why. I'm trying to send objects to the server (specifically: ajaxAction in the controller - using Zend FW). Below is the javascript code, and a summary of what the firebug console tells me.
if (!String.prototype.trim)
{
String.prototype.trim = function()
{
"use strict";
return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
};
}
function getUrl(action,controller)
{
var base,uri;
base = window.location.href.replace('http://'+window.location.host,'');
if (base.length > 1)
{
base = base.substring(1,base.length).split('/');
controller = controller || base[0];
base[0] = controller || base[0];
base[1] = action || base[1];
return '/'+base.join('/');
}
controller = controller || 'index';
action = action || 'ajax';
return base+controller+'/'+action;
}
function formalizeObject(obj,recursion)
{
recursion = recursion || false;
if (typeof obj !== 'object')
{
throw new Error('no object provided');
}
var ret = '';
for (var i in obj)
{
if (!obj.hasOwnProperty(i) || typeof obj[i] === 'function')
{
continue;
}
if (recursion)
{
ret +='['+i+']';
}
else
{
ret += (ret.length > 0 ? '&' : '') + i.toString();
}
if (typeof obj[i] === 'object')
{
ret += formalizeObject(obj[i],true);
continue;
}
ret += '='+obj[i].toString();
}
if (recursion)
{
return ret;
}
return encodeURI(ret);
}
function success()
{
if (this.readyState===4 && this.status===200)
{
console.log(this.responseText);
}
}
function ajax(str,url,method,json)
{
var ret;
json = json || false;
str = str || {};
method = method || 'POST';
url = url || getUrl();
str =
str = (typeof str === 'object' ? str : {data:str});
try
{
ret = new XMLHttpRequest();
}
catch (error)
{
try
{
ret= new ActiveXObject('Msxml2.XMLHTTP');
}
catch(error)
{
try
{
ret= new ActiveXObject('Microsoft.XMLHTTP');
}
catch(error)
{
throw new Error('no Ajax support?');
}
}
}
if (typeof ret !== 'object')
{
throw new Error('No Ajax, FFS');
}
ret.open(method, url, true);
ret.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
ret.setRequestHeader('Content-type', (json ? 'application/json' : 'application/x-www-form-urlencode'));
ret.onreadystatechange = success;
ret.send((json ? JSON.stringify(str) : formalizeObject(str)));
return true;
}
function jAjax(str,url)
{
$.ajax(
{
url : url,
data: str,
type: 'POST',
success: function(res)
{
console.log(res);
}
});
}
Four ways in which I've tried to make the Ajax request:
jAjax({data:{foo:'bar'}},getUrl());//1
jAjax({data:{foo:'bar'}},getUrl(),true);//2
ajax({data:{foo:'bar'}},getUrl());//3
ajax({data:{foo:'bar'}},getUrl(),true);//4
jAjax({data:{foo:'bar'}},getUrl());: This works just fine:
[]{"ajax":true,"controller":"index","action":"ajax","module":"default","identity":{},"data":{"foo":"Bar"}}
Parameters: data[foo] 'bar' And Source: data%5Bfoo%5D=Bar (from POST tab in FB console)
Header: application/x-www-form-urlencoded; charset=UTF-8
All of this was sent to the following url: http://www.foo.bar/index/ajax?data%5Bfoo%5D=bar
This doesn't work, however:
[]{"ajax":true,"controller":"index","action":"ajax","module":"default","identity":{}} is the response
POST tab in FB: JSON data: {foo:'Bar'} source: {"data":{"Foo":"Bar"}} (but same url is case 1)
Header: json; charset=UTF-8
This is the big one: the full request url is identical to url from case 1, as are the headers BUT when I look at the POST tab in the FB console (inspect the request) This is the only difference I can find:
case 1: Parameters: data[foo] 'bar' Source: data%5Bfoo%5D=Bar
In this case, I can't see the Parameters section, only: Source: data%5Bfoo%5D=Bar
Identical to case2, except for the url, which I think I forgot to pass through encodeURI. This case is less important for now. I think/hope I'll get this working the moment I figure out what's wrong with case 3.
In all 4 cases, the request is sent, and received. The controller action is as follows:
public function ajaxAction()
{
$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender();
$this->_helper->getHelper('AjaxContext')->addActionContext( 'ajax' , 'json' )
->initContext('json');
if($this->getRequest()->isPost() && $this->getRequest()->isXmlHttpRequest())
{
echo json_encode(array_merge(array('ajax'=>true),$this->_getAllParams()));
}
else
{
throw new Exception('no ajax call made??');
}
}
Since I'm receiving a JSON string, I'm sure the request is posted, and has the correct XMLHttpRequest header. Why then, can't I post JSON objects? Even more to the point: why is case 3 not working? What is jQuery doing that I'm not aware of? What is it, that makes case 1 to work, but not case 3?
PS: It might be irrelevant, but in a moment of madness I tried adding this: ret.setRequestHeader('Connection','close'); to the ajax function, but I noticed that, in the header that got sent out, Connection was set to keep-alive all the same. Perhaps this gives someone a clue as to what went wrong?
Thanks in advance
In case anybody wonders what was wrong:
ret.setRequestHeader('Content-type', 'application/x-www-form-urlencode');
Should have been "x-www-form-urlencoded", with a "d" in the end:
ret.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
sending a formalized object is now working, and I can get rid of jQuery :-)
I basically have an ajax function which gets the latest posts from a database, what I want to know is if no data is found what should I return seeing as returning null seems to be an issue for firebug?
php code
function getLatestChat(){
global $session, $form;
$data = $session->getLatestChat(mysql_real_escape_string($_REQUEST['withUser']),
mysql_real_escape_string($_REQUEST['ignoreMessages']));
if($data){//successful
echo json_encode($data);
}
return;
}
jquery code
function getLatestChat(){
var ignoreMessagesArr = $(".chatID").map(function(){ return this.value;}).get().join(",");
$.ajax({
traditional: true,
dataType: "json",
type: "GET", url: "include/process.php",
data:{
getLatestChat: "true",
withUser: currentCCID,
ignoreMessages: ignoreMessagesArr
},
success: function(data){
$.each(data, function(i, elem){
$('.chat-latestContainer').append(elem.value);
});
}
}
});
at the moment the method either returns the $data object or null.
You can return an empty object to represent no data in the object:
return '{}';
Or if your Javascript code expects an array, return an empty array:
return '[]';
Run a simple
if(isset($retunValue)){
//code
}
check on it to check to see if its set.
you can also try a
if(!empty($returnValue)){
//code
}
in your if code you can set it to whatever fits your needs for further use. If it's unneeded you can disregard it and just pass your function something back that wont throw an error.
Rewrite as (for example):
function getLatestChat($session, $form){
$ret = {};
$data = $session->getLatestChat(mysql_real_escape_string($_REQUEST['withUser']),
mysql_real_escape_string($_REQUEST['ignoreMessages']));
if($data){//successful
$ret = json_encode($data);
}
return $ret;
}
echo getLatestChat($session, $form);
In this situation, I'm inclined to explicitly state th response type, but maybe there are more established practices...
<?php
header('Content-Type: application/json');
// ... do stuff here: fetch data, json_encode etc.
// No data, no response
if (strlen($json) === 0) { // assuming we json encoded the data above
header('HTTP/1.1 204 No Content');
exit();
}
// everything is ok
header('HTTP/1.1 200 OK');
echo $json;
I just checked this on FF11 and the latest Firebug, and it seems to work okay.
My PHP script is having a problem decoding the JSON that I'm sending to it via AJAX.
The jQuery:
$.ajax({
url : 'admin/modifyPermissions',
type : 'post',
data : {
'JSON' : JSON
},
success : function(msg){
if(msg == '1') {
alert('Permissions saved successfully');
} else {
alert(msg);
}
}
});
The PHP script:
public function modifyPermissions(){
if(isset($_POST['JSON']) && !empty($_POST['JSON'])) {
$json = json_decode($_POST['JSON'],true);
if($json !== NULL && $json !== FALSE) {
} elseif($json === NULL){
die('The string passed is not a valid JSON object and cannot be decoded.' . "\n" . $_POST['JSON']);
} else {
die('There was an error with the JSON string');
}
} else {
die('No JSON string was sent!');
}
}
The JSON that gets passed looks well formed to me:
{"martin":{3,5},"user2":{3,4,5}}
And PHP is returning null. I have PHP 5.2.7 installed on my server, so I can't use json_last_error()
{"martin":{3,5},"user2":{3,4,5}}
Not valid JSON. Valid JSON may look like this:
{"martin":[3,5],"user2":[3,4,5]}
You're not sending valid JSON, thus the error. Look at the comment #Matt added.
So that you won't reproduce the same error, before sending it over to PHP, don't try to make your own JSON string, use what JS offers you. Example:
var obj = { key: val, okey: oval }
objJSON = JSON.stringify(obj)
// objJSON is ALWAYS going to be valid json
Your JSON is invalid.
The {} notation denotes key/value pairs, where as you're using it as an array.
Your JSON should be,
{"martin":[3,5],"user2":[3,4,5]}