I am facing trouble while posting JSON DATA to recess framework. The JSON data posted perfect from the browser end. But when i get that from the server end it becomes null. I don't know the reason.
SMPLE EXT JS CODE:
Ext.Ajax.request({
url : 'http://localhost:8888/index.php' ,
method: 'POST',
jsonData: { dining: {name: 'test',},},
success: function ( result, request ) {
alert(result.responseText);
},
});
I can get the JSON data when i am using CORE PHP. But the issue was when im with RECESS FRAMEWORK.
Finally I found the answer after deep googling. Thanks to Hirnhamster the user, http://forums.recessframework.org/.
Solution
The solution is - in contrast to finding the real problem - rather easy:
1. Step:
Open the file DefaultPolicy.class.php in recess/recess/framework.
Go to method preprocess(..).
Add the line $this->reparameterizeForFormat($request); as last command before returning.
The function should now look like this:
<?php
public function preprocess(Request &$request) {
$this->getHttpMethodFromPost($request);
$this->forceFormatFromResourceString($request);
$this->reparameterizeForFormat($request);
return $request;
}
?>
2. Step
In the same file, go to method forceFormatFromResourceString(...).
Change the line $format = substr($lastPart, $lastDotPosition + 1); to $format = strtolower(substr($lastPart, $lastDotPosition + 1));
Add the line $request->format = $format; below if($format !== '') {
The function should now look like this:
<?php
protected function forceFormatFromResourceString(Request &$request) {
$lastPartIndex = count($request->resourceParts) - 1;
if($lastPartIndex < 0) return $request;
$lastPart = $request->resourceParts[$lastPartIndex];
$lastDotPosition = strrpos($lastPart, Library::dotSeparator);
if($lastDotPosition !== false) {
$format = strtolower(substr($lastPart, $lastDotPosition + 1));
if($format !== '') {
$request->format = $format;
$mime = MimeTypes::preferredMimeTypeFor($format);
if($mime !== false) {
$request->accepts->forceFormat($format);
$request->setResource(substr($request->resource, 0, strrpos($request->resource, Library::dotSeparator)));
}
}
}
return $request;
}
?>
3. Step
In the same file, go to method reparameterizeForFormat(...).
(Be astonished that this function already exists :P).
Change Format::JSON to "json" and Format::XML to "xml"
The function should now look like this:
<?php
protected function reparameterizeForFormat(Request &$request) {
if($request->format == "json") {
$method = strtolower($request->method);
$request->$method = json_decode($request->input, true);
} else if ($request->format == "xml") {
// TODO: XML reparameterization in request transformer
}
return $request;
}
?>
4. Step
You are done.
For Detailed Solution:
http://webcache.googleusercontent.com/search?q=cache:http://forums.recessframework.org/topic/189-json-request-doesnt-insert-values-in-v02/
Try:
Ext.Ajax.request({
url : 'http://localhost:8888/index.php' ,
method: 'POST',
jsonData: { dining: {name: 'test'} },
success: function( result, request ) {
alert(result.responseText);
}
});
You're writing Javascript. Some "commas" after } aren't valid.
Related
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 */
};
I am new to the world of Kohana/php and am having some issues understanding how to get the result of an ajax request. This request is being called from a click action and is invoking the following method.
function addClickHandlerAjax(marker, l){
google.maps.event.addListener(marker, "click",function(){
console.log(l.facilityId);
removeInfoWindow();
//get content via ajax
$.ajax({
url: 'map/getInfoWindow',
type: 'get',
data: {'facilityID': l.facilityId },
success: function(data, status) {
if(data == "ok") {
console.log('ok');
}
},
error: function(xhr, desc, err) {
console.log(xhr);
console.log("Details: " + desc + "\nError:" + err);
}
}); // end ajax call
});
}
Inside of my controller I have a method
public function action_getInfoWindow(){
if ($this->request->current()->method() === HTTP_Request::GET) {
$data = array(
'facility' => 'derp',
);
// JSON response
$this->auto_render = false;
$this->request->response = json_encode($data);
}
}
I see an HTTP request in fiddler and it passed the correct facilityID parameter. However I am having some disconnect about how to connect all the pieces together.
To send a response to the browser, you should user Controller::response instead of Controller::request::response. So your code should look like this:
public function action_getInfoWindow() {
// retrieve data
$this->response->body(json_encode($data));
}
That should give you some output.
Checkout the Documentation for more detailed info.
Edit
What you could do, to make your life a bit easier, especially if you gonna use ajax requests a lot, is to create an Ajax controller. You can stuff all checks and transforms in it, and never worry about it anymore. An example controller could look like below. Also checkout the Controller_Template which is shipped as an example by Kohana.
class Controller_Ajax extends Controller {
function before() {
if( ! $this->request->is_ajax() ) {
throw Kohana_Exception::factory(500, 'Expecting an Ajax request');
}
}
private $_content;
function content($content = null) {
if( is_null( $content ) ) {
return $this->_content;
}
$this->_content = $content;
}
function after() {
$this->response->body( json_encode( $this->_content ) );
}
}
// example usage
class Controller_Home extends Controller_Ajax {
public function action_getInfoWindow() {
// retrieve the data
$this->content( $data );
}
}
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 have been making calls to php from javascript with the jquery $.ajax({}). I am finding this to be too slow particularly if ajax call is inside the code that loops through page elements. What is the best way to structure an ajax call to get the best performance?
This is a sample ajax call. Is there a better way?
// Make ajax call to update XML
$.ajax({
url: "make_update.php",
type: "POST",
data: { nodeid: scard_id, name: '', top: scard_top, left: '', width: '', height: '' },
cache: false,
/* async: true, */
success: function (response) {
if (response != '')
{
/* alert(response); */
}
}
});
The file make_update.php has this code.
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
include_once("phpshared.php");
function make_update( $nodeid, $name, $top, $left, $width, $height ) {
$nodes = new SimpleXMLElement('linkcards.xml', null, true);
$returnArray = $nodes->xpath("//LINKCARD[#ID='$nodeid']");
$node = $returnArray[0];
if ($name != null) { $node->NAME = $name; }
if ($top != null) { $node->TOP = $top; }
if ($left != null) { $node->LEFT = $left; }
if ($width != null) { $node->WIDTH = $width; }
if ($height != null) { $node->HEIGHT = $height; }
$nodes->asXML('linkcards.xml');
$formatted = formatXmlString($nodes->asXML());
$file = fopen ('linkcards.xml', "w");
fwrite($file, $formatted);
fclose ($file);
}
echo make_update(trim($_REQUEST['nodeid']),trim($_REQUEST['name']),trim($_REQUEST['top']),trim($_REQUEST['left']),trim($_REQUEST['width']),trim($_REQUEST['height']));
?>
Instead of making a separate call per page element, write server-side code that allows a whole bunch of stuff to be done with one invocation.
According to your code and question, I suspect that most overhead is created by
1) The loop of Ajax calls, which could be easily bundled in an array
2) The parsing of the linkcards.xml document
So, on the client side, your code should look like this:
var xhrData = [];
/* Enqueue all the data generated in your loop to an array */
for(var i in loop) {
xhrData.push({ nodeid: loop[i].scard_id, name: '', top: loop[i].scard_top, left: '', width: '', height: '' });
}
/* Post the whole array */
$.ajax({
url: "make_update.php",
type: "POST",
data: { data: xhrData },
cache: false,
success: function (response) {
for(var i in response) {
if (response[i] != '') {
/* alert(response[i]); */
}
}
}
});
Server side the request should be handled like this:
function make_update() {
/* somewhere here you should read the XML file */
$nodes = new SimpleXMLElement('linkcards.xml', null, true);
foreach($_REQUEST['data'] as &$element) {
/* here goes the $_REQUEST data manipulation */
}
/* and this is where the XML writing should go */
$file = fopen ('linkcards.xml', "w");
fwrite($file, $formatted);
fclose ($file);
/* return JSON encoded string back to the client */
return json_encode($_REQUEST['data'])
}
echo make_update();
Unfortunately, I can't be more specific, because your code depends on external data and I have no insight in the logic behind it. The point is, though, that you should consider fetching all the data in an array and then send the whole array to your server. On the server, it is not nescessary to continually open and close the XML file, because every call consists of the same operations.
If you even want to have a better server side performance, I would recommend to use XMLReader/XMLWriter instead of SimpleXML.