Converting object to associative array returns null
I call magento soap v2 api and in return I get a response with an object that I am trying to convert to an associative array. But when I try to do it with the json encode / decode method it returns a null array.
$result = Magento::call()->catalogProductList();
$array = json_decode(json_encode($result), true);
1) The object is not empty. 2) Casting type is not an option for me because I try to avoid adding *.
UPDATE
this is the result value that I am trying to encode.
Tinyrocket\Magento\Objects\MagentoObjectCollection Object
(
[collection:protected] => Array
(
[0] => Tinyrocket\Magento\Objects\MagentoObject Object
(
[data:protected] => Array
(
[product_id] => 9
[sku] => Tilapia
[name] => Tilapia
[set] => 4
[type] => simple
[category_ids] => Array
(
[0] => 2
[1] => 4
)
[website_ids] => Array
(
[0] => 1
)
)
)
[1] => Tinyrocket\Magento\Objects\MagentoObject Object
(
[data:protected] => Array
(
[product_id] => 10
[sku] => Deshi Rui
[name] => Deshi Rui
[set] => 4
[type] => simple
[category_ids] => Array
(
[0] => 2
[1] => 4
)
[website_ids] => Array
(
[0] => 1
)
)
)
...
...
UPDATE 2
var_export ($ result) output
Tinyrocket\Magento\Objects\MagentoObjectCollection::__set_state(array(
'collection' =>
array (
0 =>
Tinyrocket\Magento\Objects\MagentoObject::__set_state(array(
'data' =>
array (
'product_id' => '9',
'sku' => 'Tilapia',
'name' => 'Tilapia',
'set' => '4',
'type' => 'simple',
'category_ids' =>
array (
0 => '2',
1 => '4',
),
'website_ids' =>
array (
0 => '1',
),
),
)),
1 =>
Tinyrocket\Magento\Objects\MagentoObject::__set_state(array(
'data' =>
array (
'product_id' => '10',
'sku' => 'Deshi Rui',
'name' => 'Deshi Rui',
'set' => '4',
'type' => 'simple',
'category_ids' =>
array (
0 => '2',
1 => '4',
),
'website_ids' =>
array (
0 => '1',
),
),
)),
'count' => 2,
))
source to share
json_encode
converts your object according to its visible properties.
Since it Tinyrocket\Magento\Objects\MagentoObjectCollection
$collection
is a protected property, its value is not read json_encode
.
I have two solutions for this problem, one of them requires modifying the Magento source code, so I would not recommend it as it could create errors or interrupt every time the CMS is updated.
The first solution is used Reflection
, so you need PHP 5, which shouldn't be a problem since Magento needs PHP 5.4 .
The following function goes through the object \Tinyrocket\Magento\Objects\MagentoObjectCollection
to read all the properties and returns an array.
function magentoObjectCollectionToArray(\Tinyrocket\Magento\Objects\MagentoObjectCollection $object)
{
// The basic structure of your array.
$array = array(
'collection' => array()
);
// Since $collection is a protected property, we need to reflect it to read the value.
$collection_reflection = new \ReflectionProperty('\Tinyrocket\Magento\Objects\MagentoObjectCollection', 'collection');
// This method allows you to read protected and private properties for the current ReflectionProperty object.
$collection_reflection->setAccessible(true);
// Now we need to loop through all objects...
foreach ($collection_reflection->getValue($object) as $property => $value)
{
// Two cases : either a \Tinyrocket\Magento\Objects\MagentoObject object, or the $count property.
if ($value instanceof \Tinyrocket\Magento\Objects\MagentoObject)
{
// Same here, since $data is also a protected property, we need to reflect it.
$data_reflection = new \ReflectionProperty('\Tinyrocket\Magento\Objects\MagentoObject', 'data');
$data_reflection->setAccessible(true);
$array['collection'][$property] = array(
'data' => $data_reflection->getValue($value)
);
}
else
{
// We don't forget the $count property.
$array['collection'][$property] = $value;
}
}
// And you have your array without using JSON.
return $array;
}
PHP documentation links:
The second solution uses JsonSerializable
, so you need PHP 5.4 and that shouldn't be a problem either.
Once the method jsonSerialize
is implemented in a class that implements JsonSerializable, the json_encode
return value will be encoded jsonSerialize
.
So, you can change the Magento core and make the classes \Tinyrocket\Magento\Objects\MagentoObjectCollection
and \Tinyrocket\Magento\Objects\MagentoObject
to implement \JsonSerializable
and add this method jsonSerialize
in the source code:
class XXX implements \JsonSerializable
{
public function JsonSerialize()
{
// Returns all variables. Since we're in the object context, we've access to all of them.
return get_object_vars($this);
}
}
Then you get your array by calling json_encode()
/ json_decode()
as you did:
json_decode(json_encode($result), true)
While this solution may help solve your problem, I would not recommend it as it requires changes to the Magento core, which may break other modules and no longer work after an upgrade. Instead, you should create your own plugin and use the first solution that works best.
Both solutions return this array:
array (
'collection' =>
array (
0 =>
array (
'data' =>
array (
'product_id' => '9',
'sku' => 'Tilapia',
'name' => 'Tilapia',
'set' => '4',
'type' => 'simple',
'category_ids' =>
array (
0 => '2',
1 => '4',
),
'website_ids' =>
array (
0 => '1',
),
),
),
1 =>
array (
'data' =>
array (
'product_id' => '10',
'sku' => 'Deshi Rui',
'name' => 'Deshi Rui',
'set' => '4',
'type' => 'simple',
'category_ids' =>
array (
0 => '2',
1 => '4',
),
'website_ids' =>
array (
0 => '1',
),
),
),
'count' => 2,
),
)
source to share