Currently drupal_to_js serializes all php arrays as JavaScript objects; this leads to unnecessary hand cramps when dealing with simple numeric arrays. The simplest thing to do is to detect if an array is associative (based on this: http://ca3.php.net/manual/en/function.is-array.php#41179 ) and then do the right thing:

function drupal_to_js($var) {
  switch (gettype($var)) {
    case 'boolean':
    case 'integer':
    case 'double':
      return $var;
    case 'resource':
    case 'string':
      return '"'. str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($var)) .'"';
    case 'array':
      $output = array();
      if(!(is_array($var) && array_keys($var)!==range(0,sizeof($var)-1))) {
        foreach($var as $v) {
          $output[] = drupal_to_js($v);
        }
        return '[ ' . implode(', ', $output)." ]";
      }
    case 'object':
      $output = array();
      foreach ($var as $k => $v) {
        $output[] = $k .': '. drupal_to_js($v);
      }
      return '{ '. implode(', ', $output) .' }';
    default:
      return 'null';
  }
}

simple tests for this:

$data1 = array('x', 'y');
$data2 = array('x'=>array('x'=>'y', 'q'), 'y'=>1234);
$data3 = array($data1, array('x'=>'y','foo'=>1));
$data4 = array(4=>'x', 2=>'y');

echo "data1: ".drupal_to_js($data1)."\n";
echo "data2: ".drupal_to_js($data2)."\n";
echo "data3: ".drupal_to_js($data3)."\n";
echo "data4: ".drupal_to_js($data4)."\n";

expected output:

data1: [ "x", "y" ]
data2: { x: { x: "y", 0: "q" }, y: 1234 }
data3: [ [ "x", "y" ], { x: "y", foo: 1 } ]
data4: { 4: "x", 2: "y" }

Note: this also places drupal_to_js closer in functionality to PHP-JSON ( http://www.aurore.net/projects/php-json/ ), so if you have this extension compiled in you can do fancy things like this:

function _json_encode($data){
  if(is_callable('json_encode')) {
	return json_encode($data);
  } else {
	return drupal_to_js($data);
  }
}
CommentFileSizeAuthor
#1 php_is_array.patch830 bytesgreggles
arrayfix.patch269 bytesanisotropic
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

greggles’s picture

Version: 4.7.0-beta2 » x.y.z
Status: Active » Needs review
FileSize
830 bytes

I created a patch based upon anisotropic's code in this block. I then created a test site using this and nothing blew up, but I'm not sure what a good test for this particular code would be so I can't really claim it's been 'tested'. I just wanted to move it to "patched, code needs review" stage and make it easier for others to test out.

I created the patch against a cvs checkout current as of this comment. I'm also changing the version since his description of the code is still accurate against that cvs version.

greggles’s picture

I didn't even notice that it already had a patch...

I guess the status deserved to be changed already.

I still have some value added: the later patch is in the Drupal standard patch format.

Thox’s picture

I don't know about this particular method for checking the type of array, but in essence I agree that it should be done. If nothing else, it requires a comment to explain what is going on.

Steven’s picture

Status: Needs review » Needs work

Code style is bad. And the switch fallthrough should be indicated with a comment.

Steven’s picture

Status: Needs work » Fixed

I committed a modified version of this patch as part of 47510. The is_array() check in the above code is redundant.

Anonymous’s picture

Status: Fixed » Closed (fixed)