Can't select specific element in JSON parsed array with JavaScript - javascript

So I have a mySQL database and I am pulling data from it to my website and want to change content with the help of JavaScript. The problem is that I can't seem to select specific elements out of my data which I received from the databse.
Here is how I pull data and parse it into a JSON string:
while($row = $result->fetch_assoc()) {
$return_array = array("region" => $row['region'], "capital" => $row['capital'], "surface_area" => $row['surface_area'], "land_area" => $row['land_area'], "water_area" => $row['water_area'], "global_area_rank" => $row['global_area_rank'], "land_boundary" => $row['land_boundary'], "bordering_countries" => $row['bordering_countries'], "coastline" => $row['coastline'], "climate" => $row['climate'], "terrain" => $row['terrain'], "avg_elevation" => $row['avg_elevation'], "highest_elevation" => $row['highest_elevation'], "lowest_elevation" => $row['lowest_elevation'], "natural_resources" => $row['natural_resources'], "land_use" => $row['land_use'], "irrigated_land" => $row['irrigated_land'], "natural_hazards" => $row['natural_hazards']);
}
echo json_encode($return_array);
In my JavaScript method I call this PHP script and receive the parsed JSON string which I temporarily output in a single div:
$.post('ajax/retrieve_data.php', { sel1: sel1, sel2: sel2 }, function(data) {
var return_array = $.parseJSON(data);
$('div#test-div').text(return_array.region);
});
The output however, just shows the entire JSON string with curly brackets and all identifiers, which means that the return_array.region selector does not work. I tried it with indices and all sorts of other syntax, but it did not work. Everywhere on the internet everyone uses this syntax to select specific elements, but it somehow doesn't work. I probably have a very stupid error in there, but I appreciate every help. I just can't seem to see the error.

My guess is that your PHP script isn't returning data with the proper Content-Type header. Make sure, in your PHP script, you run the following:
header('Content-Type: application/json');
This must come before echoing anything.

Related

PHP - Javascript result inside MySQL

I don't understand why every column has good results but the screen column has code inside and not the actual SCREEN SIZE (result of the code).
<?php
#$data = $_SERVER['HTTP_USER_AGENT']."|";
#$data.= $_SERVER['HTTP_CF_CONNECTING_IP']."|";
$width = " <script>document.write(screen.width); </script>";
$height = " <script>document.write(screen.height); </script>";
$data.=$width;
$data.=$height;
$finz = explode("|",$data);
$ag = $finz[0];
$ip = $finz[1];
$sc = $finz[2];
$query1 = $db->prepare("INSERT INTO `checks` (user,type,ip,screen,agent) values (:user,:type,:ip,:screen,:agent)");
$query1->execute(array(
'user' => $USER['username'],
'type' => 'Red Flower',
'ip' => $ip,
'screen' => $sc,
'agent' => $ag
));
$row2 = $query->fetch();
?>
Can somebody tell me how to make the code insert the values of the JavaScript output without using POST AJAX/JQuery etc?
The embedded JavaScript won't be evaluated until your template reaches the client. It's not something the PHP interpreter understands. It's just a string. You have to execute this code in JavaScript and send it back to the server, there's no other way.
You will need to send a request back to the server containing the results of the evaluated JavaScript before performing the query against your database.
I realize this is something you were trying to avoid.

unable to get json data from server

My server side code is:
$bus = array(
'meaning' => $name
);
$jsonstring = json_encode($bus);
echo $_GET['callback'].'(' . $jsonstring. ')';
the value displayed on the screen is correct - ?word=heart({"meaning":"heart"})
but when I am reading it with following code its printing the value of meaning as 11200665987893779229_1460521505942
$(document).ready(function(){
$.getJSON('http://mydomain?callback=?','word=heart',function(res){
document.getElementById('print').innerText=''+res.meaning;
});
});
but when I do this:
$bus = array(
'meaning' => 'heart'
);
it's printing the correct value i.e heart
I am not getting why this is happening and how to get the correct value (I am accessing data from my different domain).
JSON.parse() converts any JSON String passed into the function, to a JSON Object.
$(document).ready(function(){
$.getJSON('http://mydomain?callback=?','word=heart',function(res){
obj = JSON.parse(res);
document.getElementById('print').innerText=''+obj.meaning;
});
});
a similar post is here

using AJAX query to pass javascript array to php

After reading through quite a few posts here, (and even just straight copying code,) I still cannot figure out why this is not working.
On my main page, I have a textbox that a user pastes data into. Upon paste, this script runs (this and the ajax query below are in the same script function):
var lines = $('textarea').val().split('\n'); //create array from pasted data
I now have a JavaScript array with the pasted data. I'm trying to send this over to a separate PHP file that I will load into a div on this main page by doing the following:
$.ajax({
type: 'POST',
url: 'return.php',
data: {lines:lines},
success:function(data){
$("#info").load("return.php");
}
});
for (i=0; i < lines.length; i++) { // log the output
if (lines[i]){
console.log("line ", i , lines[i]);
}
}
In my return.php file, I have this:
$lines = $_REQUEST['lines'];
echo '<pre>';
echo($lines);
echo '</pre>';
My console.log is outputting the array perfectly, but for some reason it is not making its way over to return.php, as my echo is blank.
What am I doing wrong?
The response I get from return.php is:
<pre>testArrayArray
(
[0] => DL4004-13-F
[1] => S1G-13-F
[2] => ZXMP3A13FTA
[3] => B260A-13-F
[4] => S1J-13-F
[5] => S3B-13-F
[6] => SSN1N45BTA
[7] => GBJ1010-F
[8] => BPW20RF
[9] => T3035H-6I
[10] => ZXMP7A17KTC
[11] =>
)
</pre>
The success handler on your ajax request is calling return.php with nothing and loading it into #info.
Change success to instead do:
$("#info").html(data)
The $lines variable in your PHP code is an array, not a string. If you have the errors turned on, PHP should warn you that you're doing an "Array to string conversion" (at least it does for me using your code).
You can't echo an array like that, you have to iterate through the results somehow.

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