JQuery unable to parse JSON string created by json_encode - javascript

I am currently in a bind, JQuery is unable to parse the following json strings
{ "query":"Unit",
"suggestions":
[ {"value":"Mr Ruto Kimutai ","data":88},{"value":"Mr Kimani Karanja","data":79} ] }
{"query":"Unit",
"suggestions":
[{"value":"Mr Ruto Kimutai ","data":88},{"value":"Mr Kimani Karanja","data":79}]}
The above strings when parse through JSON.parse create the following arror:
SyntaxError: JSON.parse: unexpected non-whitespace character after
JSON data at line 1 column 112 of the JSON data
The PHP code which creates the string above is this:
public function getCustomerSuggestions($name){
$customers = $this->model->where('name','LIKE','%'.$name.'%')->show();
if(count($customers)>=1){
foreach($customers as $customer){
$list[] = ['value' => ucfirst($customer->name),'data' => $customer->id];
}
}
else{
$list[] = ['value' => 'No Customers Found', 'data'=> NULL];
}
$full_list['query'] = 'Unit';
$full_list['suggestions'] = $list;
return json_encode($full_list);
}
As you can see I am using the function json_encode to create the JSOn string so there should be no issue but it still doesnt work.
Edit
The json is sent using an autocomplete tool called DevBridge Autocomplete which takes the JSON strings and creates a suggestion list. The code I am using is
$('input[name=\"customer\"]').devbridgeAutocomplete({
serviceUrl: '".SITE_PATH."/ajax/admin/quotes/getcustomer',
minChars: 1,
onSearchStart: function (query){
var searchinput = $(this).val();
$('.autocomplete-suggestions').html('Searching: '+searchinput);
},
onSelect: function(suggestion){
var selection = $(this).val(suggestion.value);
$('input[name=\"customerid\"]').val(suggestion.data);
$.get('".SITE_PATH."/ajax/admin/quotes/getcustomerdetails',{id: suggestion.data},
function(response){
var obj = $.parseJSON(response);
$.each(obj, function(key, value){
$('#'+key).val(value);
});
});
}
});

It seems you have two JSON objects after each other. That's simply invalid. There can only be a single value at the root of a JSON "document". If you want to send down multiple objects, you need to put them in an array.
It seems getCustomerSuggestions is called multiple times and the return value of each call is returned to the client. Instead, the method should return an array, the caller should collect the return values in an array and JSON encode that array.

Well, your JSON string is NOT valid.
It should be,
[
{ "query":"Unit",
"suggestions":
[ {"value":"Mr Ruto Kimutai ","data":88},{"value":"Mr Kimani Karanja","data":79} ] }
,
{"query":"Unit",
"suggestions":
[{"value":"Mr Ruto Kimutai ","data":88},{"value":"Mr Kimani Karanja","data":79}]}
]
But as Felix Kling said, check your PHP code.

Related

Get first word of string inside array - from return REST

I try get the sessionid before REST function, but in the case if I does not convert toString(); show only numbers (21 22 2e ...).
See this image:
1º:
Obs.: Before using split.
!!xxxxxxx.xxxxx.xxxxxxx.rest.schema.xxxxResp {error: null, sessionID: qdaxxxxxxxxxxxxxj}
My code:
var Client = require('./lib/node-rest-client').Client;
var client = new Client();
var dataLogin = {
data: { "userName":"xxxxxxxx","password":"xxxxxxxx","platform":"xxxxx" },
headers: { "Content-Type": "application/json" }
};
client.registerMethod("postMethod", "xxxxxxxxxxx/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
// parsed response body as js object
// console.log(data); all return, image 1
// raw response
if(Buffer.isBuffer(data)){
data = data.toString('utf8'); // if i does not convert to string, return numbers, see image 1..
console.log(data); //all inside image 2, and i want just value from sessionid
var output = data;
var res = output.split(" "); // using split
res = res[4].split("}", 1);
}
console.log(res); //image 3
});
I tested with JSON.parse and JSON.stringify and it did not work, show just 'undefined' for all. After convert toString();, And since I've turned the values ​​into string, I thought of using split to get only the value of sessionid.
And when I used split, all transform to array and the return is from console.log(data), see image 2:
2º:
Obs.: After use split and convert to array automatically.
And the return after use split is with the conditions inside my code:
3º:
And the return after use split is with the conditions inside my code:
[ 'bkkRQxxxxxxxxxxxxx' ]
And I want just:
bkkRQxxxxxxxxxxxxx
I would like to know how to solve this after all these temptations, but if you have another way of getting the sessionid, I'd be happy to know.
Thanks advance!
After converting the Buffer to a string, remove anything attached to the front with using data.substr(data.indexOf('{')), then JSON.parse() the rest. Then you can just use the object to get the sessionID.
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
data = data.substr(data.indexOf('{'));
obj = JSON.parse(data);
console.log(obj.sessionID);
}
EDIT:
The issue you are having with JSON.parse() is because what is being returned is not actually JSON. The JSON spec requires the properties to be quoted ("). See this article
If the string looked like this, it would work: {"error": null, "sessionID": qdaxxxxxxxxxxxxxj}
Because the json is not really json, you can use a regular expression to get the info you want. This should get it for you.
re = /(sessionID: )([^,}]*)/g;
match = re.exec(data);
console.log(match[2]);
EDIT 2: After fully reading the article that I linked above (oops haha), this is a more preferable way to deal with unquoted JSON.
var crappyJSON = '{ somePropertyWithoutQuotes: "theValue!" }';
var fixedJSON = crappyJSON.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');
var aNiceObject = JSON.parse(fixedJSON);

Getting array values in php from jQuery post

I am trying to send an array from jQuery post to PHP.
But I am not getting any values with the below code.
Could anyone help ?
jQuery
$("body").on("click", ".js-form",function(event){
var arr = [];
i = 0;
$('.addcolor').each(function() {
if( $(this).text()=="done"){
arr[i++]= $(this).data('request-id');
}
});
alert(arr);
$.post("../ajax/save_Request.php", {requestids:arr, action:'save_request' })
});
alert(arr)-> prints 11,24,35 (eg)
But I am not getting any values in the following PHP variable.
PHP
$ids = ( isset($_POST['requestids']) ) ? $_POST['requestids'] : 0;
Try with this 'choices[]'
$.post( "test.php", { 'choices[]': [ "Jon", "Susan" ] } );
See more in : jQuery.post and search the key "Pass arrays of data to the server". I think that you missed []. Try it and return me the result.
Try converting the array to a JSON string first, using
var json = JSON.stringify(arr);
Now that it's a JSON string, you can simply pass it through a hidden field. Then, once you get the string back from the PHP page, you can turn it back into an array using
$array = json_decode($arr, true);
where $arr is the JSON string.
I had a similar problem with trying to pass an array from JQuery to another PHP page and this worked for me.

getJSON data add array item to variable

I am using this script to retrive JSON data from a file to my page.
$.getJSON('json/data.json', function(data) {
$('#getJSON-results').html(JSON.stringify(data));
});
<div id="getJSON-results"></div>
Right now it jsut displays all the data from JSON file as a string on the page.
How would I take the data from my JSON file and place each array into a variable? My data in the JSON file looks like this:
[{"target": "summarize(first, \"1d\", \"sum\")", "datapoints": [[38.393148148148143, 1423958400], [90.800555555555633, 1424044800], [159.06037037037032, 1424131200], [245.5933333333335, 1424217600], [126.94796296296299, 1424304000], [120.37111111111113, 1424390400], [103.04148148148151, 1424476800], [99.273796296296368, 1424563200], [89.38203703703708, 1424649600], [92.970462962963012, 1424736000], [105.62666666666664, 1424822400], [110.33962962962967, 1424908800], [118.54981481481482, 1424995200], [100.08018518518523, 1425081600], [92.52277777777779, 1425168000], [98.647619047618974, 1425254400], [94.585000000000008, 1425340800], [85.568796296296284, 1425427200], [157.82222222222222, 1425513600], [109.7596296296296, 1425600000], [112.53324074074077, 1425686400], [89.392592592592649, 1425772800], [97.253518518518518, 1425859200], [73.424629629629635, 1425945600], [92.377592592592578, 1426032000], [76.117870370370397, 1426118400], [77.83953703703699, 1426204800], [66.643518518518533, 1426291200], [63.748055555555531, 1426377600], [137.30018518518517, 1426464000], [53.480648148148134, 1426550400]]},
{"target": "summarize(second, \"1d\", \"sum\")", "datapoints": [[2.7291600529100535, 1423958400], [5.7797089947089892, 1424044800], [3.4261574074074059, 1424131200], [5.0516335978835958, 1424217600], [6.2272420634920582, 1424304000], [11.752605820105822, 1424390400], [7.8688624338624269, 1424476800], [5.7305555555555525, 1424563200], [5.2784391534391499, 1424649600], [6.4652380952380897, 1424736000], [4.7690277777777741, 1424822400], [4.1451587301587258, 1424908800], [8.4178902116402039, 1424995200], [4.7948611111111061, 1425081600], [4.8153835978835939, 1425168000], [5.3873148148148111, 1425254400], [7.2819378306878262, 1425340800], [5.2084391534391488, 1425427200], [8.098492063492051, 1425513600], [5.6563822751322697, 1425600000], [5.3091468253968195, 1425686400], [4.7850396825396793, 1425772800], [3.8716931216931179, 1425859200], [3.1934325396825369, 1425945600], [3.2083531746031722, 1426032000], [3.3434391534391512, 1426118400], [3.6162235449735438, 1426204800], [3.2094179894179891, 1426291200], [2.3699537037037026, 1426377600], [4.3973544973544945, 1426464000], [2.1901388888888893, 1426550400]]},
{"target": "summarize(third, \"1d\", \"sum\")", "datapoints": [[5.3710185185185182, 1423958400], [11.25367724867724, 1424044800], [8.2990079365079268, 1424131200], [8.710694444444437, 1424217600], [9.6381216931216898, 1424304000], [9.3845105820105807, 1424390400], [9.7305820105820047, 1424476800], [8.6268055555555474, 1424563200], [10.589166666666673, 1424649600], [10.235462962962957, 1424736000], [10.455892857142853, 1424822400], [14.282407407407405, 1424908800], [17.774404761904758, 1424995200], [18.154120370370364, 1425081600], [16.249543650793651, 1425168000], [15.29764550264551, 1425254400], [16.267671957671972, 1425340800], [20.121488095238096, 1425427200], [27.007685185185196, 1425513600], [17.577962962962971, 1425600000], [17.020873015873018, 1425686400], [14.627685185185191, 1425772800], [15.824821428571433, 1425859200], [11.837579365079364, 1425945600], [13.292539682539683, 1426032000], [12.064074074074073, 1426118400], [12.279457671957676, 1426204800], [9.3799074074073978, 1426291200], [7.8777314814814732, 1426377600], [13.161825396825407, 1426464000], [7.2587499999999956, 1426550400]]}]
I am new to using JSON and would also appreciate any advice on the approach I'm taking.
How can I now make this data accsessable outside the getJSON?
$.getJSON('json/data.json', function(data) {
yourData = data;
makeMeGlobal = yourData[0];
});
console.log(makeMeGlobal.datapoints);
Changing your function to the following will result in an object you can then reference normally:
$.getJSON('json/data.json', function(data) {
yourData = data;
});
You could then get the first set of datapoints like this:
yourData.datapoints[0]
Should be:
data.forEach(function (obj) {
// obj now has each JSON object in this array
var test = obj.target;
}
When you get a JSON from AJAX, it's already ready for use in the browser. This is one of the nice perks of using JSON over XML.
It's already an array, because the original JSON string was parsed by jQuery. If you use stringify, you will get a string which contains the JSON representing the array (not useful for your purposes, as it's the same string returned by the server).
For example:
$.getJSON('json/data.json', function(data) {
// Here, data is already an array.
var data_length = data.length;
for (var i = 0; i < data_length; i++) {
var obj = data[i]; // Here we have an object from the array
alert("I have an object which target is " + obj.target);
}
});
You need to iterate through json to retrieve the value you need and append the html.More infor # https://stackoverflow.com/a/18238241/909535 Something like this
`$.getJSON('json/data.json', function(data){
data.forEach(
function(val, index, array) {
//val.target will have target attribute's value
//val.datapoints is a array which you can iterate
}
);
}
);`

Properly returning a JSON object with an embedded JS function

Updated Post
I have a solution for that problem which works with me so far (only tested on Firefox).
My main goal was to dynamically update a Flot graph with Ajax. I also need to dynamically update the axis styles and you can do this by the tickFormatter option. To avoid the problems I previously had, I simply insert the desired return string in the PHP array and JSON encode that array. After returned to the Ajax function I create a new function using the javascript Function() constructor (Link). I hope this helps someone.
Ajax
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json'
})
.success(function(data) {
var datas = data[0]; // fetch data array
var options = data[1]; // fetch options array
var xReturn = options.xaxes[0].tickFormatter; // fetch return string
var yReturn = options.yaxes[0].tickFormatter;
var xFunc = new Function("val", "axis", xReturn); // create function
var yFunc = new Function("val", "axis", yReturn);
options.xaxes[0].tickFormatter = xFunc; // update tickFormatter with function
options.yaxes[0].tickFormatter = yFunc;
$.plot($("#yw0"), datas, options);
})
.error(function(data) {
$("#error").html(data.responseText); // show error in separate div
});
PHP array
$options = array(
'legend' => array(
'position' => 'nw',
'show' => true,
'margin' => 10,
'backgroundOpacity' => 0.5
),
'grid' => array(
'clickable' => true,
'hoverable' => true
),
'pan' => array('interactive' => true),
'zoom' => array('interactive' => true),
'axisLabels' => array('show' => true),
'xaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"' // enter whatever return value you need
)
),
'yaxes' => array(
array(
'axisLabel' => 'someUnit',
'tickFormatter' => 'return "foo bar"'
)
)
);
I skip the data array as it looks similar. Both arrays get combined and JSON encoded.
public function actionSomeControllerWhichCreatesJSONdata() {
$returnArray = array($data, $options);
echo json_encode($returnArray);
return true;
}
The resulting array looks like the one I've posted in the bottom of this post.
Original Post
I'm trying for hours now, but I can't get this to work.
I have an Ajax request which gets a JSON object as return value on success. This works fine as long as I don't use a JS function in my JSON array. So my JSON array looks as follows (after json_encode):
[{
"data": [{
{1,2},
{3,4},
}],
"function": "function(){return \"foo bar\";}"
}]
In order to get rid of the "'s in the function string. I use str_replace and replace the quoted string with an unquoted one. This then looks like so:
[{
"data": [{
{1,2},
{3,4},
}],
"function": function(){return "foo bar";}
}]
The plain json_encode works fine and my Ajax function reads it as a JSON object. After I replace the string it turns out that the return value is no longer a JSON object but a plain text string. I've tried to parse the string again with jquery.parseJSON() but this results in the syntax error:
SyntaxError: JSON.parse: unexpected keyword at line 1 column 396 of the JSON data
Ajax function:
$.ajax({
url: 'someControllerWhichCreatesJSONdata',
data: 'some Value',
type: 'post',
cache: false,
datatype: 'json' // or text when trying to parse
})
.success(function(data) {
console.log(data);
var dat = jQuery.parseJSON(data); // trying to parse (only when dataType: "text")
var datas = dat[0]; // or data[0] when datType = json
var options = dat[1]; // ---
$.plot($("#yw0"), datas, options); // trying to update a FLOT window
})
.error(function(data) {
console.log("error");
$("#error").html(data.responseText); // show error in separate div
});
So when using this function and setting the return type to "json", it produces an error. If the return type is "text" and I try to parse the string I get the error above. Is there any solution for this problem or am I doing something completely wrong?
Thank's for your help!
UPDATE
Sorry of course my JSON data is not valid! As I said, my JSON object gets created by json_encode which I guess should get the syntax right. The plain array after son_encode looks like:
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid": {
"clickable":true,
"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel": {
"unit":"Jy",
"id":null,
"name":null},
"tickFormatter":"$tickFormatter$",
"position":"right"
}]
and after str_replace I get
[[{
"data":[[0.0042612,0.0042612]],
"label":"WISE.W3: Cutri et. al 2012",
"lines":{"show":false},
"points":{"show":true,"radius":3}}],
{
"legend": {
"position":"nw",
"show":true,
"margin":10,
"backgroundOpacity":0.5},
"grid":{"clickable":true,"hoverable":true},
"pan":{"interactive":true},
"zoom":{"interactive":true},
"axisLabels":{"show":true},
"axisLabel":{"unit":"Jy","id":null,"name":null},
"tickFormatter":function(val, axis){return val.toExponential(2)},
"position":"right"
}]
Adeno pointed it out already, your JSON syntax is not valid.
Please try to validate your JSON with a linter, like http://jsonformatter.curiousconcept.com/
This is a bit better:
[{"data":[["1","2"],["3","4"]],"function":"function(){return \"foo bar\";}"}]
And the other thing is: you should not manually deserialize the JSON. All newer versions of jQuery will automatically deserialize JSON based on the response's content-type header.
You already set dataType to json for the ajax request.
The response is JSON and will be de-serialized.
So you can directly use
.success: function(response) {
console.log(response.data);
console.log(response.function);
}
Answer for the questions/issue from the comments:
Now you created invalid JSON again, because "tickFormatter" : function(val, axis){return val.toExponential(2)}, misses the quotes around the function string.
Before you insert the string with str_replace(), you need to take care of escaping and quoting.
You may need a little helper function, which properly escapes a string - to be valid JSON.
you need to use str_replace() correctly: not replacing the outer quotes, just the inner $tickFormatter$.
Wait.. i will provide an example:
// we already have an array, which is JSON encoded
// now you want to insert additional JSON content.
// therefore we use a token replace approach.
// valid JSON - with $token$
$json = '[{"data":[["1","2"],["3","4"]],"tickFormatter":"$tickFormatter$"}]';
// the (future) javascript function is a string.
// it's not properly escaped or quoted to be JSON
// this allows for copy and pasting JS into PHP
$unescaped_functionString = 'function(){return "foo bar";}';
// in order escapre properly, we need a json escaping helper
/**
* #param $value
* #return mixed
*/
function escapeJsonString($value) { # list from www.json.org: (\b backspace, \f formfeed)
$escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
$replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
$result = str_replace($escapers, $replacements, $value);
return $result;
}
// then we escape the function string
$functionString = escapeJsonString($unescaped_functionString);
// now its ready to be inserted into the existing JSON,
// where token $tickFormatter$ is defined
// the token must be in single quotes. you replace just the $token$ and not "$token$".
$json = str_replace('$tickFormatter$', $functionString, $json);
echo $json;
// The result is valid JSON again:
// [{"data":[["1","2"],["3","4"]],"tickFormatter":"function(){return \"foo bar\";}"}]
Next step:
The ajax request is made, the json data is transferred to the client and you want to execute the function you passed in.
So the new question is "How to call/exec a JavaScript function from a string - without using eval?"
In general tunneling is a bad practice, see: Is it valid to define functions in JSON results?
Anyway, there a different ways to do this:
Referencing: http://everythingfrontend.com/posts/studying-javascript-eval.html
eval() - evil, but works.
setTimeout()
setTimeout(" function ", 0);
new Function()
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
document.write
document.write('<script> JS </script>')
data URI
var s = document.createElement('script');
s.src = 'data:text/javascript,' + encodeURIComponent('alert("lorem ipsum")')
document.body.appendChild(s);
JSON cannot contain functions like this.
You can however use Javascript to inject the function into the DOM, so what you want to do is skip the str_replace part and simply create a <script type="text/javascript"></script> element in the DOM and insert the data.function property into there.

How could I JSON.parse nested object inside array

I'm trying to pass this structure on a PHP/Ajax response:
{"asn":"167", "jte":"[[1381547700000,0.0], [1381548600000,0.0]]", "visitas":"[{x:1380596400000,text:'HELLO WORLD.',title:'X'}]"}
But JSON.parse returns an error.
SyntaxError: JSON.parse: expected property name or '}'
Without the "visitas" object everything runs fine. Is it possible to "nest" as this?
UPDATE:
Ajax Part:
$.ajax({
type: 'post',
url: 'cxxx.php',
data: { asn: asn },
success: function(p){
p = JSON.parse(p);
jusante=JSON.parse(p.jusante);
montante=JSON.parse(p.montante);
vazao=JSON.parse(p.vazao);
minima=JSON.parse(p.minima);
fator=JSON.parse(p.fator);
visitas=JSON.parse(p.visitas)
and PHP part:
$v="[";
while(odbc_fetch_row($res)){
$datavisita = odbc_result($res, "DATA_VISITA");
$descricaovisita = odbc_result($res, "DESCRICAO_VISITA");
$login = odbc_result($res, "LOGIN");
$descricaomotivo = odbc_result($res, "DESCRICAO_MOTIVO");
$id_motivo=odbc_result($res, "ID_MOTIVO");
$datavisita=date("U", strtotime($datavisita))*1000;
$descricaovisita=preg_replace("/\r|\n/", "", $descricaovisita);
$v.="{x:$datavisita,text:'$descricaovisita',title:'$id_motivo'}, ";
}
$v=rtrim($v,", ")."]";
echo "{\"asn\": \"$asn\", \"description\": \"$description\", \"jusante\": \"$o\", \"montante\": \"$m\", \"vazao\": \"$f\", \"minima\": \"$mn\", \"fator\": \"$fp\", \"visitas\": \"$v\" }";
the Json you are using is valid, I checked it on JSONLint, so your problem might be with serialization, just make sure your "visitas" object is serialized correctly because the problem might be happening because it's the only member with an object value inside
Remove the quotes around the visitas array:
var json = JSON.parse('{"asn": "167","jte": "[[1381547700000,0.0], [1381548600000,0.0]]", "visitas": [{"x": "1380596400000", "text":"HELLOWORLD.","title":"X"}]}');
While the outermost JSON object looks fine, there might be a problem with the nested one!
If you are trying to parse the nested JSON element "visitas" you might have a problem in the fact that your property names (e.g. x, text and title) are not enclosed in quotation marks ("). This is of course a bit tricky since you are trying to include the visitas element as a string.
A solution might be to include the visitas element as a proper JSON element instead.
You need to escape the single quotes. I imagine you are surrounding the above in single quotes when you pass it to JSON.parse.
The below works.
JSON.parse('{"asn":"167", "jte":"[[1381547700000,0.0], [1381548600000,0.0]]", "visitas":"[{x:1380596400000,text:\'HELLO WORLD.\',title:\'X\'}]"}');
Note the slashes before the single quotes inside the string.
I would do the following:
var jsondata = {
"asn": "167",
"jte": "[[1381547700000,0.0], [1381548600000,0.0]]",
"visitas": "[{x:1380596400000,text:'HELLO WORLD.',title:'X'}]"
};
jsondata = JSON.stringify(jsondata);
then send it to php
var postdata = { data : jsondata};
var url = "<?php echo base_url(); ?>"+"test";
$.post(url, postdata, function(result){
console.log(result);
});
sice your php result is echoed the wrong way you should fix that first. Create arrays so that you can easily use the JSON_ENCODE function like so:
$array = array(
"asn" => "test_asn",
"description" => "description_test",
"jusante" => "jusante_test",
"montante" => "montante_test",
"vazao" => "vazao_test",
"minima" => "minima_test",
"fator" => "fator_test",
"visitas" => "visitas_test"
);
$json = json_encode($array);
echo $json;

Categories

Resources