How to decode json string into half array/ half object?

257 Views Asked by At

I have the following json string

$str = '{"icwsCallQueue":{"1002598152":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259815260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"},"1002598162":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259816260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"}}}';

If I decode it using json_decode($str) I get the following

stdClass Object
(
    [icwsCallQueue] => stdClass Object
        (
            [1002598152] => stdClass Object
                (
                    [AccoRDI_account_id] => 
                    [AccoRDI_mid] => 
                    [Eic_CallDirection] => O
                    [Eic_CallIdKey] => 100259815260150624
                    [Eic_CallState] => Disconnected
                    [Eic_ConferenceId] => 
                    [Eic_ConferenceMembers] => 
                    [Eic_ImmediateAccess] => 1
                    [Eic_LocalName] => Full Name
                    [Eic_LocalUserId] => username
                    [Eic_MonitorsCombinedCount] => 0
                    [Eic_Muted] => 
                    [Eic_ObjectType] => Call
                    [Eic_ParentConferenceId] => 
                    [Eic_RemoteAddress] => 307
                    [Eic_RemoteName] => username-test
                    [Eic_State] => I
                )

            [1002598162] => stdClass Object
                (
                    [AccoRDI_account_id] => 
                    [AccoRDI_mid] => 
                    [Eic_CallDirection] => O
                    [Eic_CallIdKey] => 100259816260150624
                    [Eic_CallState] => Disconnected
                    [Eic_ConferenceId] => 
                    [Eic_ConferenceMembers] => 
                    [Eic_ImmediateAccess] => 1
                    [Eic_LocalName] => Full Name
                    [Eic_LocalUserId] => username
                    [Eic_MonitorsCombinedCount] => 0
                    [Eic_Muted] => 
                    [Eic_ObjectType] => Call
                    [Eic_ParentConferenceId] => 
                    [Eic_RemoteAddress] => 307
                    [Eic_RemoteName] => username-test
                    [Eic_State] => I
                )

        )

)

The problem with this is that I can't access a property with only an integer. I can't do this $icwsCallQueue->100259152->Eic_State so what I need to do some how is convert my decoded string to something like this

stdClass Object
(
    [icwsCallQueue] => Array
        (
            [1002598152] => stdClass Object
                (
                    [AccoRDI_account_id] => 
                    [AccoRDI_mid] => 
                    [Eic_CallDirection] => O
                    [Eic_CallIdKey] => 100259815260150624
                    [Eic_CallState] => Disconnected
                    [Eic_ConferenceId] => 
                    [Eic_ConferenceMembers] => 
                    [Eic_ImmediateAccess] => 1
                    [Eic_LocalName] => Full Name
                    [Eic_LocalUserId] => username
                    [Eic_MonitorsCombinedCount] => 0
                    [Eic_Muted] => 
                    [Eic_ObjectType] => Call
                    [Eic_ParentConferenceId] => 
                    [Eic_RemoteAddress] => 307
                    [Eic_RemoteName] => username-test
                    [Eic_State] => I
                )

            [1002598162] => stdClass Object
                (
                    [AccoRDI_account_id] => 
                    [AccoRDI_mid] => 
                    [Eic_CallDirection] => O
                    [Eic_CallIdKey] => 100259816260150624
                    [Eic_CallState] => Disconnected
                    [Eic_ConferenceId] => 
                    [Eic_ConferenceMembers] => 
                    [Eic_ImmediateAccess] => 1
                    [Eic_LocalName] => Full Name
                    [Eic_LocalUserId] => username
                    [Eic_MonitorsCombinedCount] => 0
                    [Eic_Muted] => 
                    [Eic_ObjectType] => Call
                    [Eic_ParentConferenceId] => 
                    [Eic_RemoteAddress] => 307
                    [Eic_RemoteName] => username-test
                    [Eic_State] => I
                )

        )

)

so I can access the records like this $icwsCallQueue['100259152']->Eic_State

on the other hand if I decoded the string like this json_decode($str, true) everything will be presented as array which is not what am I looking for.

Any idea on how to decode the string with array when array must be used and object when array can be avoided?

1

There are 1 best solutions below

0
On

You can cast array to stdclass and stdclass to array when needed.

First of all json_decode($str, true) to get the associative version of the data. Then iterate through the most inner parts of the data and cast arrays back to objects again. Now it's possible to use stdclass properties as accessors.

  $str = '{"icwsCallQueue":{"1002598152":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259815260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"},"1002598162":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259816260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"}}}';
  $json = json_decode($str, true);
  foreach($json["icwsCallQueue"] as $key => $element) {
    $json["icwsCallQueue"][$key] = (object)$element;
  }
  var_dump($json["icwsCallQueue"]['1002598152']->Eic_CallIdKey);
  var_dump($json["icwsCallQueue"]['1002598162']->Eic_CallIdKey);

There was another and simpler solution but I couldn't make it work. That's why I have to iterate all the array.

  $str = '{"icwsCallQueue":{"1002598152":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259815260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"},"1002598162":{"AccoRDI_account_id":"","AccoRDI_mid":"","Eic_CallDirection":"O","Eic_CallIdKey":"100259816260150624","Eic_CallState":"Disconnected","Eic_ConferenceId":"","Eic_ConferenceMembers":"","Eic_ImmediateAccess":"1","Eic_LocalName":"Full Name","Eic_LocalUserId":"username","Eic_MonitorsCombinedCount":"0","Eic_Muted":"","Eic_ObjectType":"Call","Eic_ParentConferenceId":"","Eic_RemoteAddress":"307","Eic_RemoteName":"username-test","Eic_State":"I"}}}';
  $json = json_decode($str);
  $jsonArray = (array)$json->icwsCallQueue;
  var_dump($jsonArray["1002598152"]);
  //PHP Notice:  Undefined offset: 1002598152 in 

Looks like PHP does not cast to array properly with integer keys. Or there is something I am missing here.

The rest is up to your imagination.