php json_encode + modernizr object - php

I'm looking for better and more robust solution for echoing out yepnope feature tests using php. The output should look something like :
{
test : Modernizr.geolocation,
yep : 'normal.js',
nope : ['polyfill.js', 'wrapper.js']
}
From an output like:
$l10n = array(
'test' => 'Modernizr.geolocation',
'yep' => "'normal.js'",
'nope' => array("'polyfill.js'", "'wrapper.js'")
);
Obviously, there is the issue of quotation marks being wrapped around the json object. I can't help but wonder if there's a different class altogether that caters to creating mixed javascript objects containing raw javascript as well as strings.

json_encode returns the JSON representation of a value, the point is JSON representation is not a javascript object, JSON is a subset of the javascript object literal, so you need to do the convert in javascript.
var l10n = <?php echo json_encode($l10n); ?>;
if (l10n.test === "Modernizr.geolocation") {
l10n.test = Modernizr.geolocation;
}

Related

Highchart data parsed after ajax answer

I received from a jquery ajax function a response like :
["{y:55,color:'red'}", "{y:21}", "{y:12}", "{y:6}", "{y:3}", "{y:3}"]
In my PHP code, I encode via json_encode in an array :
foreach($pp as $value){
$tmp[]='{y:'.round(100*$pp/$sum_pp,0).'}';
}
echo json_encode(array("tableau"=>$tmp));
I'd like to have this, to be used in my Highchart graph :
[{y:55,color:'red'}, {y:21}, {y:12}, {y:6}, {y:3}, {y:3}]
How do I have to format my array to graph my answer ? I do this way to be able to change color on one column in the serie.
Thanks for your time.
If you have the possibility to change the PHP code I would opt to output something similar to the series object used in Highcharts, see http://api.highcharts.com/highcharts#series.
That is an object which looks like this:
{
data: [y1, y2, y3],
color: '#FF0000'
}
That would make your PHP code look like this:
foreach($pp as $value){
$tmp[] = round(100*$pp/$sum_pp,0);
}
echo json_encode(array(
"data" => $tmp,
"color" => '#FF0000'
));
On a side note, filling $tmp like you did in the question is bad. A better way would be:
foreach($pp as $value){
$tmp[] = array('y' => round(100*$pp/$sum_pp,0));
}
echo json_encode(array("data"=>$tmp));
As this will create a "propper" object when parsed in your Javascript. Both examples above in my code will produce something you can use directly in Highcharts. Please note that the series parameter takes an array of series. So in your javascript you would have to do:
series: [
data: response
]
Where response is the is the the output from the json_encode in you PHP script.

Convert JSON list to php array

I am passing a list of numbers from a page to PHP serialized in JSON
{"items":"[1,2,3,4]"}
in my URL it is just
...&items={"items":[1,2,3,4]}
I decode this in PHP
$json = $_GET["items"];
$arr = json_decode($json, true);
I get an array
Array ( [items] => [1,2,4] )
But when I try a foreach on arr["items"] and print out each value, all I get is a single value
[1,2,4]
This is the code I am using to iterate
foreach($res["items"] as $value)
echo $value;
How come I am not getting something like
1
2
4
Look closely at your json string:
{"items":"[1,2,3,4]"}
Look closer:
"[1,2,3,4]"
You are saying that items is a string containing:
"[1,2,3,4]"
Remove the " and you'll be fine.
Your serialization is wrong. Should be:
{"items":[1,2,3]}
To get rid of problems like that use JSON.stringify in JS:
var myData = {"items" : [1,2,3]},
queryString = 'data='+encodeURIComponent(JSON.stringify(myData));
for IE < 8 it has to be included from external script (see here) :
<!--[if lt IE 8]><script src="/js/json2.js"></script><![endif]-->
Anyway much easier would be to send it already as an array:
items[0]=1&items[1]=2&items[2]=3
This way you can send also more complex structures:
data[items][0]=1&data[items][1]=2
// on PHP side will become
$_GET['data'] = array('items' => array(1,2))

PHP: Recursive htmlspecialchars on object

I want to establish a generic sanitizer for my data that comes from various sources. With sanitizing I mean (at this stage) applying htmlspecialchars to strings. Now, the data that comes from these sources can be anything from an object to an array to a string, all nested (and complicated), and the format is always a bit different.
So I thought of a recursive htmlspecialchars function that applies itself to arrays and objects, and only applies htmlspecialchars to strings, but how do I walk an object recursively?
Thanks.
EDIT: I think I should have mentioned this - I am actually building a RIA that relies heavily on JS and JSON for client-server communication. The only thing the server does is fetching stuff from the database and returning it to the client via JSON, in the following format:
{"stat":"ok","data":{...}}
Now as I said, data could be anything, not only coming from a DB in the form of strings, but also coming from an XML
The workflow to process the JSON is as follows:
Fetch data from the DB/XML (source encoding is iso-8859-1)
Put them into the "data" array
Recursively convert from iso-8859-1 to utf-8 using
private function utf8_encode_deep(&$input) {
if (is_string($input)) {
$input = $this -> str_encode_utf8($input);
} else if (is_array($input)) {
foreach ($input as &$value) {
$this -> utf8_encode_deep($value);
}
unset($value);
} else if (is_object($input)) {
$vars = array_keys(get_object_vars($input));
foreach ($vars as $var) {
$this -> utf8_encode_deep($input -> $var);
}
}
}
Use PHP's json_encode to convert the data into JSON
Send (echo) the data to the client
Render the data using JS (e.g. putting into a table)
And somewhere in between that, the data should be somehow sanitized (at this stage only htmlspecialchars). Now the question should have been: Where to sanitize, using what method?
You can try the following
class MyClass {
public $var1 = '<b>value 1</b>';
public $var2 = '<b>value 2</b>';
public $var3 = array('<b>value 3</b>');
}
$list = array();
$list[0]['nice'] = range("A", "C");
$list[0]['bad'] = array("<div>A</div>","<div>B</div>","<div>C</div>",new MyClass());
$list["<b>gloo</b>"] = array(new MyClass(),"<b>WOW</b>");
var_dump(__htmlspecialchars($list));
Function Used
function __htmlspecialchars($data) {
if (is_array($data)) {
foreach ( $data as $key => $value ) {
$data[htmlspecialchars($key)] = __htmlspecialchars($value);
}
} else if (is_object($data)) {
$values = get_class_vars(get_class($data));
foreach ( $values as $key => $value ) {
$data->{htmlspecialchars($key)} = __htmlspecialchars($value);
}
} else {
$data = htmlspecialchars($data);
}
return $data;
}
Output Something like
array
0 =>
array
'nice' =>
array
0 => string 'A' (length=1)
1 => string 'B' (length=1)
2 => string 'C' (length=1)
'bad' =>
array
0 => string '<div>A</div>' (length=24)
1 => string '<div>B</div>' (length=24)
2 => string '<div>C</div>' (length=24)
3 =>
object(MyClass)[1]
...
array
0 =>
object(MyClass)[2]
public 'var1' => string '<b>value 1</b>' (length=26)
public 'var2' => string '<b>value 2</b>' (length=26)
public 'var3' =>
array
...
You would only want to escape when outputting into HTML. And you cannot output a complete array or object into HTML, so escaping everything seems invalid.
You have one level of indirection because of your JSON output. So you cannot decide in PHP what context the data is used for - JSON is still plain text, not HTML.
So to decide whether any data inside the JSON must be escaped for HTML we must know how your Javascript is using the JSON data.
Example: If your JSON is seen as plain text, and contains something like <b>BOLD</b>, then the expected outcome when used inside any HTML is exactly this text, including the chars that look like HTML tags, but no bold typesetting. This will only happen if your Javascript client handles this test as plain text, e.g. it DOES NOT use innerHTML() to place it on the page, because that would activate the HTML tags, but only innerText() or textContent() or any other convenience method in e.g. jQuery (.text()).
If on the other hand you expect the JSON to include readymade HTML that is fed into innerHTML(), then you have to escape this string before it is put into JSON. BUT you must escape the whole string only if you do not want to add any formatting to it. Otherwise you are in a situation that uses templates for mixing predefined formatting with user content: The user content has to be escaped when put into HTML context, but the result must not - otherwise Javascript cannot put it into innerHTML() and enable the formatting.
Basically a global escaping for everything inside your array or object most likely is wrong, unless you know for everything that it will be used in a HTML context by your Javascript.
function htmlrecursive($data){
if (is_array($data) && count($data) > 1){
foreach ($data as &$d){
$d = htmlrecursive($d);
}
} else if (!is_array($data)){
return htmlspecialchars($data);
}
else {
return htmlspecialchars($data[0])
}
}
htmlrecursive($array);
For objects you need to implement The ArrayAccess interface then you can do a array walk recursive
Also check this question Getting an object to work with array_walk_recursive in PHP

Assigning identifier/name to JSON object in PHP

I'm grabbing data from a mysql database and encoding a JSON object with PHP to use in JS.
On the PHP end, I did this
while($row = mysql_fetch_array($result))
{
$jmarkers = array(
'id'=> $row['id'],
'lat' => $row['lat'],
'lng' => $row['lng'],
etc...
);
array_push($json, $jmarkers);
}
$jsonstring = json_encode($json);
echo $jsonstring;
I can access the data in JS using jQuery, and I made an array to save the JSON data:
$.getJSON("getjson.php", function(data)
{
myMarkers = data;
console.log(myMarkers);
});
I'd planned to access the data in the myMarkers array inside loop, with a statement like this:
var tempLat = myMarkers.jmarkers[i].lat;
The problem is my JSON objects aren't called jmarkers or anything else, they have this generic name "Object" when I print them to the console:
Object { id="2", lat="40.6512", lng="-73.9691", more...},
So I'm not sure how to point to them in my JS array. I looked the PHP JSON encode function and I can't see where to set or change the object name. Any suggestions? Thank you!
That's to be expected. JSON is essentially the right-hand-side of an assignment operation:
var x = {'foo':'bar'};
^^^^^^^^^^^^^---- JSON
The x part is not included, since that's simply the name of the object. If you want your jmarkers text included, it'll have to be part of the data structure you're going to encode:
$arr = array(
'jmarkers' => array(...your data here...);
);
But all this does is add another layer to your data structure for no useful reason.
$jmarkers is simply the identifier on the PHP side for the JSON object. When it gets passed, it converts the array value into a JSON-encoded string and therefore loses the identifier as a result.
In your PHP code at the moment, array_push($json, $jmarkers) is appending an array to your current $json array. You are therefore instancing a two-dimensional array, which will not be retrievable by the jmarkers identifier in your Javascript code. Simply retrieve the data using myMarkers[i] instead.
You... don't. The whole thing is an object. You only need to refer to the elements within.
alert(myMarkers.id);

Parsing a JSON string to array, not object

I've got a PHP array and echo that into javascript with json encode, i need to do it this way because it's going to be very dynamic. This is the code it echo's:
{"notempty":true}
And i use this to, convert it to javascript:
var myarray = eval('(' + json + ')');
For some reason it creates an object instead of an array and for that reason i cant use .length or a for loop.
Does someone know what im doing wrong here?
Thanks
You're trying to treat an Object like an Array, and an Object is not an Array, it is an Object.
Any time you see {} in JSON, that means "What is contained within these hallowed brackets is a dynamic object". When you see [], that means "Behold! I am an Array" (there are notable exceptions to this one: jQuery does some special work with to make itself look like an array).
So, in order to iterate through an Object, you'll want to use for... in.
// eval BAD unless you know your input has been sanitized!.
var myObj = JSON.parse('{"notempty":true}');
// personally, I use it in for... in loops. It clarifies that this is a string
// you may want to use hasOwnProperty here as sometimes other "keys" are inserted
for( var it in myObj ) console.log( "myObj["+it+"] = " + myObj[it] );
{} is an object, which contains one attribute named notempty. If you want an array, it'd have to be
[{"notempty":true}]
which is an array with a single element at index 0, which is an object with the single attribute 'notempty';.
By default, if you use encode an assoc array in php, it will become a js object when you decode. In order to have it be an array, you need to make it an array in php:
PHP:
$arr = "['notempty','notempty2','notempty3']";
Otherwise, you should convert it to an array in JS, but that seems to me a waste since looping through the object in javascript is so much easier:
Javascript:
var arr = new Array();
for(var i in obj) arr[i] = obj[i];
You can use jQuery to parse it into an array like this:
var p = [];
$.each(jsonData, function (key, val) {
p.push([val.propertyOne, val.propertyTwo]);
});
I am presuming of course that you want to parse JSON, not an array or any other string.

Categories