Reputation: 4404
I have the following object, here printed as an array. This object is built from a SOAP request.
AdminInfo Object (
[Supplier] => Supplier Object (
[Party] => Party Object (
[OrgInfo] => OrgInfo Object (
[CompanyName] => Bobs
[IDInfo] => Array of IDInfo Objects (
[0] => IDInfo Object (
[IDQualifierCode] =>
[IDNum] =>
)
[1] => IDInfo Object (
[IDQualifierCode] => CompanyID
[IDNum] => 83e26599-d40g-4cba-9791-7d7c83de282c
)
[2] => IDInfo Object (
[IDQualifierCode] => TID
[IDNum] => BOBTID01020304
)
[3] => IDInfo Object (
[IDQualifierCode] => Token
[IDNum] => c784570e-044d-42c8-98fe-af9f7c1747f5
)
)
)
[ContactInfo] => ContactInfo Object (
[ContactJobTitle] =>
[Communications] => Comm Object (
[CommQualifier] =>
[CommPhone] =>
[CommEmail] =>
[Address] => Address Object (
[Address1] =>
[Address2] =>
[City] =>
[StateProvince] =>
[PostalCode] =>
[CountryCode] =>
)
)
[ContactName] => PersonName Object (
[FirstName] =>
[MiddleName] =>
[LastName] =>
)
)
)
)
[Company] => Company Object (
[Party] => Party Object (
[OrgInfo] => OrgInfo Object (
[CompanyName] => SF
[IDInfo] =>
)
[ContactInfo] =>
)
)
[Facility] => Facility Object (
[Party] => Party Object (
[OrgInfo] => Array of OrgInfo Objects (
)
[ContactInfo] => ContactInfo Object (
[ContactJobTitle] => Owner
[Communications] => Array of Comm Objects(
[0] => Comm Object (
[CommQualifier] => WP
[CommPhone] => 1234567890
)
[1] => Comm Object (
[CommQualifier] => SA
[Address] => Address Object (
[Address1] => 123 NE 14th St
[City] => Nowhere
[StateProvince] => ND
[PostalCode] => 12345
[CountryCode] => US
)
)
[2] =>
[3] =>
)
[ContactName] => PersonName Object (
[FirstName] => Bob
[MiddleName] =>
[LastName] => Tester
)
)
)
)
)
What I want to do is to remove all the empty elements and be returned with this object
AdminInfo Object (
[Supplier] => Supplier Object (
[Party] => Party Object (
[OrgInfo] => OrgInfo Object (
[CompanyName] => Bobs
[IDInfo] => Array of IDInfo Objects (
[0] => IDInfo Object (
[IDQualifierCode] =>
[IDNum] =>
)
[1] => IDInfo Object (
[IDQualifierCode] => CompanyID
[IDNum] => 83e26599-d40g-4cba-9791-7d7c83de282c
)
[2] => IDInfo Object (
[IDQualifierCode] => TID
[IDNum] => BOBTID01020304
)
[3] => IDInfo Object (
[IDQualifierCode] => Token
[IDNum] => c784570e-044d-42c8-98fe-af9f7c1747f5
)
)
)
)
)
[Company] => Company Object (
[Party] => Party Object (
[OrgInfo] => OrgInfo Object (
[CompanyName] => SF
)
)
)
[Facility] => Facility Object (
[Party] => Party Object (
[ContactInfo] => ContactInfo Object (
[ContactJobTitle] => Owner
[Communications] => Array of Comm Objects (
[0] => Comm Object (
[CommQualifier] => WP
[CommPhone] => 1234567890
)
[1] => Comm Object (
[CommQualifier] => SA
[Address] => Address Object (
[Address1] => 123 NE 14th St
[City] => Nowhere
[StateProvince] => ND
[PostalCode] => 12345
[CountryCode] => US
)
)
)
[ContactName] => PersonName Object (
[FirstName] => Bob
[LastName] => Tester
)
)
)
)
)
These attempts don't do it AT ALL; variable $AdminInfo
is the Object above...
From solution here: strip null values of json object
$json = json_encode($AdminInfo);
$result = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $json);
$echo $result;
From solution here: How to remove null values from an array?
$json = json_encode($AdminInfo); // convert to JSON
$arr = (array)json_decode($json); // convert to an array
$object = (object) array_filter((array) $arr); // filter the array
$result = json_encode($object); // convert it back to JSON
echo $result;
From here: PHP - How to remove empty entries of an array recursively?
function array_remove_empty($haystack)
{
foreach ($haystack as $key => $value) {
if (is_array($value)) {
$haystack[$key] = array_remove_empty($haystack[$key]);
}
if (empty($value)) {
unset($haystack[$key]);
}
}
return $haystack;
}
$json = json_encode($AdminInfo); // convert to JSON
$arr = (array)json_decode($json); // convert to an array
print_r(array_remove_empty($arr)); // run through array_remove_empty function and print
From solution here: Remove items from multidimensional array in PHP
function cleanArray($array) {
if (is_array($array)) {
foreach ($array as $key => $sub_array)
{
$result = cleanArray($sub_array);
if ($result === false) {
unset($array[$key]);
} else {
$array[$key] = $result;
}
}
}
if (empty($array)) {
return false;
}
return $array;
}
$json = json_encode($AdminInfo); // convert to JSON
$arr = (array)json_decode($json); // convert to an array
print_r(cleanArray($arr)); // run through cleanArray function and print
Edit
AdminInfo object as JSON:
{
"Supplier":{
"Party":{
"OrgInfo":{
"CompanyName":"Bobs",
"IDInfo":[
{
"IDQualifierCode":null,
"IDNum":""
},
{
"IDQualifierCode":"CompanyID",
"IDNum":"83e26599-d40g-4cba-9791-7d7c83de282c"
},
{
"IDQualifierCode":"TID",
"IDNum":"BOBTID01020304"
},
{
"IDQualifierCode":"Token",
"IDNum":"c784570e-044d-42c8-98fe-af9f7c1747f5"
}
]
},
"ContactInfo":{
"ContactJobTitle":"",
"Communications":{
"CommQualifier":null,
"CommPhone":"",
"CommEmail":"",
"Address":{
"Address1":"",
"Address2":"",
"City":"",
"StateProvince":null,
"PostalCode":"",
"CountryCode":null
}
},
"ContactName":{
"FirstName":"",
"MiddleName":"",
"LastName":""
}
}
}
},
"Company":{
"Party":{
"OrgInfo":{
"CompanyName":"SF",
"IDInfo":null
},
"ContactInfo":null
}
},
"Facility":{
"Party":{
"OrgInfo":[
],
"ContactInfo":{
"ContactJobTitle":"",
"Communications":[
{
"CommQualifier":null,
"CommPhone":"",
"CommEmail":"",
"Address":{
"Address1":"",
"Address2":"",
"City":"",
"StateProvince":null,
"PostalCode":"",
"CountryCode":null
}
},
null,
null,
null
],
"ContactName":{
"FirstName":"Bob",
"MiddleName":"",
"LastName":"Tester"
}
}
}
}
}
Upvotes: 3
Views: 2497
Reputation: 4513
Requirements: Recursively scan nested arrays pruning out empty branches / items.
This is another 'tree walk'.
The only 'tricky' part is letting the processing higher up the tree know whether to add the current item into the output tree or not.
The function that processes a node will return an array that has a 'keep value' flag as well as the value to keep.
JSON Converted to array: Full Working code at eval.in
Output preserves original JSON Data Type: Full Working code at eval.in
Code:
function processList(array $list)
{
$listResult = ['keepValue' => false, // once set true will propagate upward
'value' => []];
foreach ($list as $name => $item ) {
if (is_null($item)) { // see is_scalar test
continue;
}
if (is_scalar($item)) { // keep the value?
if (!empty($item) || strlen(trim($item)) > 0) {
$listResult['keepValue'] = true;
$listResult['value'][$name] = $item;
}
} else { // new list... recurse
$itemResult = processList($item);
if ($itemResult['keepValue']) {
$listResult['keepValue'] = true;
$listResult['value'][$name] = $itemResult['value'];
}
}
}
return $listResult;
}
Run the function:
$source = json_decode($json, true);
$result = processList($source);
print_r($result['value']);
Output:
Array
(
[Supplier] => Array
(
[Party] => Array
(
[OrgInfo] => Array
(
[CompanyName] => Bobs
[IDInfo] => Array
(
[1] => Array
(
[IDQualifierCode] => CompanyID
[IDNum] => 83e26599-d40g-4cba-9791-7d7c83de282c
)
[2] => Array
(
[IDQualifierCode] => TID
[IDNum] => BOBTID01020304
)
[3] => Array
(
[IDQualifierCode] => Token
[IDNum] => c784570e-044d-42c8-98fe-af9f7c1747f5
)
)
)
)
)
[Company] => Array
(
[Party] => Array
(
[OrgInfo] => Array
(
[CompanyName] => SF
)
)
)
[Facility] => Array
(
[Party] => Array
(
[ContactInfo] => Array
(
[ContactName] => Array
(
[FirstName] => Bob
[LastName] => Tester
)
)
)
)
)
Upvotes: 1
Reputation: 21463
seriously don't got time to test it, but edit: tested it, had a bug in the original code (had clean_iterable(NULL,$v);
instead of clean_iterable(NULL,$v[$key]);
, fixed it, this seem to work:
function clean_iterable(Iterable $v=NULL,Iterable &$vv=NULL):Iterable{
if(isset($vv)){
$v=&$vv;
}
if(empty($v)){
return $v;
}
foreach($v as $key=>$val){
if(empty($val)){
unset($v[$key]);
}elseif(is_iterable($val)){
clean_iterable(NULL,$v[$key]);
}
}
return $v;
}
Upvotes: 0
Reputation: 2006
After a little bit of headscratching I came up with a recursive function that, like I suggested earlier, converts the object into an array to check if the variables are set to null.
If all variables inside that object are null, the parent is indexed to set the reference of the object to null.
I tried to explain and document the code as best as I can.
Please don't just copy the code and be done with it but read it trough and try to learn from the code I supplied.
/**
Unsets all empty variables in $object
*/
function loopTrough(&$object, &$parent = null, $key = null, $objectIsArray = false, $parentIsArray = false)
{
// Keep track of amount of vars and amount of null vars
$vars = 0;
$null = 0;
foreach($object as $index => $value)
{
$vars = $vars + 1;
// Also check if is array
$isArray = is_array($value);
// Check if is object
if (is_object($value) || $isArray) // using value here is save
{
// Loop trough the new object (or array) we found
if ($objectIsArray)
{
loopTrough($object[$index], $object, $index, $isArray, $objectIsArray);
}
else
{
loopTrough($object->{$index}, $object, $index, $isArray, $objectIsArray);
}
}
// Check if is null
if ($objectIsArray)
{
if (!isset($object[$index]) || $object[$index] == ""){
$null = $null + 1;
// We don't want to show null
unset($object[$index]);
}
}
else
{
if (!isset($object->{$index}) || $object->{$index} == "") // use $object->{index} here, and not $value because $value does not change when object reference is changed
{
$null = $null + 1;
// We don't want to show null
unset($object->{$index});
}
}
}
// If there are as much null variables as variables
if ($vars == $null && $parent !== null && $key !== null)
{
// Set the parent reference to null
if ($parentIsArray) // Example exludes arrays, uncomment this if you want values in arrays to be recurisvely set to null
{
// unset($parent[$key]);
}
else
{
unset($parent->{$key});
}
}
}
class Test
{
public $one;
public $two;
}
$test = new Test();
$test->one = new Test();
$test->one->two = "On";
$test->two = new Test();
$test->two->one = new Test();
var_dump($test);
loopTrough($test);
var_dump($test);
Upvotes: 1
Reputation: 2006
Like I suggested earlier you COULD convert the object
into an array
and recursively loop trough the elements to check if they are null
.
The recursive function is going to be quite complicated since you don't just want to remove null variables, but remove everything that contains null only variables.
Heres an example without the recursion which just removes null
variables from an object
:
class A
{
public $var = "aVar";
public $var1 = null;
}
$a = new A();
var_dump($a);
$array = (array)$a;
foreach($array as $key => $value)
{
if (is_null($value)){
unset($array[$key]);
}
}
var_dump($array);
Upvotes: 0