drupal_to_js needs to differentiate between associative and numeric php arrays

anisotropic - December 30, 2005 - 20:21
Project:Drupal
Version:x.y.z
Component:base system
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed
Description

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);
  }
}

AttachmentSize
arrayfix.patch269 bytes

#1

greggles - January 24, 2006 - 20:29
Version:4.7.0-beta2» x.y.z
Status:active» needs review

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.

AttachmentSize
php_is_array.patch 830 bytes

#2

greggles - January 24, 2006 - 20:31

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.

#3

Thox - January 24, 2006 - 21:01

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.

#4

Steven - January 25, 2006 - 15:08
Status:needs review» needs work

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

#5

Steven - February 5, 2006 - 19:21
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.

#6

Anonymous - February 19, 2006 - 19:31
Status:fixed» closed
 
 

Drupal is a registered trademark of Dries Buytaert.