I ran into a similar problem with the open-source mail server Postal. In this case, I used the API to send an email message with two recipients. The API returns JSON, which I want to process to get the message ID Postal has assigned to each message. The JSON string decodes to a series of nested objects, according to print_r.
pObj: stdClass Object
(
[status] => success
[time] => 0.28
[flags] => stdClass Object
(
)
[data] => stdClass Object
(
[message_id] => a122e786-6c32-4085-b1ed-023e5923ca38@rp.postal.domain.com
[messages] => stdClass Object
(
[name1@domain1.com] => stdClass Object
(
[id] => 180
[token] => AblVpj6UW2wh
)
[name2@domain2.com] => stdClass Object
(
[id] => 181
[token] => io5wgEXO1boH
)
)
)
)
Looking at the structure, the first few layers are easy to extract. The trouble is that the messages object has attributes named for each recipient email address. Without knowing these address values a priori, I couldn't access the individual recipient objects programmatically to get at the message id.
I also examined this object using var_dump() and var_export(). That's where I saw this strange and misleading syntax: "stdClass::__set_state(array(". But there are no arrays at all in this object. In reality, this structure contains nothing but nested objects and attributes.
This situation was giving me fits until I asked the right question: what are the names of an object's attributes?
Now the programmatic solution is relatively easy because PHP has a function for that. I used get_object_vars() to get an array of attributes in the messages object. By simply looping on that array, I could then access the id and token attributes of each address. Here's the code, with a sample JSON response from Postal.
define('_EOL', "\n");
$json='{"status":"success","time":0.28,"flags":{},"data":{"message_id":"a122e786-6c32-4085-b1ed-023e5923ca38@rp.postal.domain.com","messages":{"name1@domain1.com":{"id":180,"token":"AblVpj6UW2wh"},"name2@domain2.com":{"id":181,"token":"io5wgEXO1boH"}}}}';
$pObj=json_decode($json);
$str='<pre>pObj: '.print_r($pObj, true)._EOL._EOL;
$str.=' - status='.$pObj->status._EOL;
$msgVars=get_object_vars($pObj->data->messages);
foreach ($msgVars as $varKey=>$msgObj)
{
$str.=' - '.$varKey.':'._EOL;
$str.=' - id='.$msgObj->id._EOL;
$str.=' - token='.$msgObj->token._EOL;
}
echo($str.'</pre>');
What made this hard is that the Postal design uses variable attribute names in the messages object. I would have made messages an array and put the email address into an attribute named address along with the attributes id and token. But it is what it is, and I hope this helps someone else.