Search code examples
phprecursionphp-5.3json

Converting json to array with recursive method?


I am trying to convert json string inside an array into array,

$config = array(
    "type"  => '{"category":"admin","page":"page"}',
    "say"     => "Hello",
    "php"   => array(
        "say"     => "no",
        "type"  => '{"category":"admin","page":"page"}',
        "gran"  =>array(
            "name" => "Hi"
        )
    )
);

My working code,

class objectify
{

    public function json_to_array($array, $recursive = true)
    {
        # if $array is not an array, let's make it array with one value of former $array.
        if (!is_array($array)) $array = array($array);

        foreach($array as $key => $value)
        {
            if($recursive === false) $array[$key] = (!empty($value) && is_string($value) && json_decode($value) != NULL) ? json_decode($value, true): $value;
                else $array[$key] = (!empty($value) && is_string($value) && json_decode($value) != NULL) ? json_decode($value, true): is_array($value) ? self::json_to_array($array) : $value;
        }

        return $array;
    }
}

It works fine without recursive method but breaks when I want to do the recursive as you can see in my code above,

$object = new objectify();
$config = $object->json_to_array($config);
print_r($config);

error message,

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2048 bytes) in C:\wamp\www\test\2012\php\set_variable.php on line 79

I just want to get this result,

Array
(
    [type] => Array
        (
            [category] => admin
            [page] => page
        )
    [say] => Hello
        (
            [say] => no
            [type] => {"category":"admin","page":"page"}
            [gran] => Array
                (
                    [name] => Hi
                )

        )

)

EDIT:

$config = 'type={"category":"admin","page":"page"}&text_editor={"name":"mce-basic"}&parent_id=self&subtitle=true&description=true&content_1=true&script_1=true&primary_image=true';
parse_str($config,$array);
print_r($array);

result,

Array
(
    [type] => {"category":"admin","page":"page"}
    [text_editor] => {"name":"mce-basic"}
    [parent_id] => self
    [subtitle] => true
    [description] => true
    [content_1] => true
    [script_1] => true
    [primary_image] => true
)

Solution

  • Quick solution:

    $full_array = array_map('json_decode', $array);
    

    If not all your parameters are JSON, and you want actual arrays instead of stdClass objects, you may have to do this:

    function json_decode_array($input) { 
      $from_json =  json_decode($input, true);  
      return $from_json ? $from_json : $input; 
    }
    $full_array = array_map('json_decode_array', $array);
    

    If you have more levels of nested arrays outside of the JSON, then you have to do your own recursion. Try this version of objectify:

    class objectify
    {
      public function json_mapper($value, $recursive = true) {
        if (!empty($value) && is_string($value) &&
            $decoded = json_decode($value, true)) {
          return $decoded;
        } elseif (is_array($value) && $recursive) {
          return array_map('objectify::json_mapper', $value);
        } else {
          return $value;
        }
      }
    
      // currying, anyone?
      public function json_mapper_norecurse($value) { 
         return objectify::json_mapper($value, false);
      }
    
      public function json_to_array($array, $recursive = true)
      {
        # if $array is not an array, let's make it array with one value of
        # former $array.
        if (!is_array($array)) {
          $array = array($array);
        }
    
        return array_map(
          $recursive ? 'objectify::json_mapper' 
                     : 'objectify::json_mapper_norecurse', $array);
      }
    }
    

    Which works fine for me on both of your sets of sample data.