Using Generators to flatten a JSON doc in PHP

To flatten a JSON like this:

{
   "addresses" : [
     {
       "line1" : "123 Livingstone Rd",
       "id" : 23444555,
       "addressSummaryType": "Building",
       "subAddresses": {
         "Level1": [
           {
             "line1" : "Level 2",
             "id" : 266887373,
             "Level2": [
               {
                 "line1": "Suite 201",
                 "id" : 276888890
               }
             ]
           }
         ]
       }
     },
     {
       "addressSummaryType": "Building",
       "line1" : "124 Livingstone Rd",
       "id" : 2562672
     }
   ]
 }

to:

array(2) {
  ["id"]=>
  int(23444555)
  ["address"]=>
  string(18) "123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(266887373)
  ["address"]=>
  string(26) "Level 2 123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(276888890)
  ["address"]=>
  string(36) "Suite 201 Level 2 123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(2562672)
  ["address"]=>
  string(18) "124 Livingstone Rd"
}

I used the following code:

foreach(flattenAddress($addressObj->addresses) as $flattenedAddress) {
      var_dump($flattenedAddress);
 }

 function flattenAddress($addresses, $baseAddress = '', $level = 0)
 {
     foreach ($addresses as $address) {
         $nextLevel = "Level" . ($level + 1);
         if (property_exists($address, "addressSummaryType")) { //root
             $baseAddress = $address->line1;
             yield ["id" => $address->id, "address" => $baseAddress];
             if (property_exists($address, "subAddresses")) {
                 yield from flattenAddress($address->subAddresses->{$nextLevel}, $baseAddress, ($level + 1));
                 continue; // recurse don't reset level
             }
         } else { //subaddresses
             $subAddress =  $address->line1 . " " . $baseAddress;
             yield ["id" => $address->id, "address" => $subAddress];
             if (property_exists($address, $nextLevel)) {
                 yield from flattenAddress($address->{$nextLevel}, $subAddress, ($level + 1));
                 continue; // recurse don't reset level
             }
         }
         $level = 0; //reset for next root
     }
 }


Leave a Reply

Your email address will not be published. Required fields are marked *