PHP:从对象中删除空项

3
我有以下对象,这里打印为一个数组。该对象是从SOAP请求构建的。
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
                )
            )
        )
    )
)

我想做的是删除所有空元素并返回此对象。
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
                )
            )
        )
    )
)

这些尝试根本行不通;变量$AdminInfo是上面的对象...

从这里的解决方案:strip null values of json object
$json = json_encode($AdminInfo);
$result = preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $json);
$echo $result;

以下解决方案来自:如何从数组中删除空值?

$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;

从这里开始:PHP - 如何递归地删除数组中的空条目?
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

以下方案来自:如何在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

编辑
将AdminInfo对象转换为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"
                }
            }
        }
    }
}

in JSON or what format??? - MB34
我们可以尝试复制粘贴上述代码并尝试解决问题,而不是手动重新创建对象。 - Patrick Q
你可以将对象转换为数组,循环遍历并取消所有没有变量的变量。使用递归循环遍历每个对象。 - Joas
@Joas,这就是两个尝试的解决方案所做的内容,但它们并没有起作用。 - MB34
@PatrickQ 刚刚将对象添加为 JSON。 - MB34
显示剩余3条评论
4个回答

1

经过一番思考,我想出了一个递归函数,就像我之前建议的那样,将对象转换为数组以检查变量是否设置为null。

如果该对象内的所有变量都为null,则父级被索引以将对象的引用设置为null。

我尽力解释和记录代码。

请不要只是复制代码并完成它,而是仔细阅读并尝试从我提供的代码中学习。

/**
    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);

还是不行,请使用我上面发布的JSON对象。 - MB34
@MB34 我已经编辑了代码以支持数组。这使得代码更加混乱,但它可以工作。 - Joas
即使通过那段代码运行,也无法删除所有的空对象。显然,它只是将值设置为null。 - MB34
@MB34 现在的代码提供了一个与示例完全相同的副本,除了您示例中的不一致之外。如果有些东西不完全符合您的要求,您可以进一步自行修改代码以满足您的需求。 - Joas

1

要求:递归扫描嵌套数组并剪枝为空的分支/项。

这是另一种“树遍历”。

唯一“棘手”的部分是让高层树形结构处理知道是否将当前项目添加到输出树中。

处理节点的函数将返回一个包含“保持值”标志以及要保留的值的数组。

JSON转换为数组:完整工作代码在eval.in上

输出保留原始的JSON数据类型:完整工作代码在eval.in上

代码:

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']);

输出:

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
                                )
                        )
                )
        )
)

警告:empty() 函数的一个问题是它会删除字符串字面值 "0" 和数字 0。if(empty($v) && $v!=="0" && $v!==0){} - hanshenrik

0

正如我之前建议的那样,你可以将 object 转换为 array,并递归地循环遍历元素以检查它们是否为 null

由于您不仅要删除空变量,而且要删除所有只包含空变量的内容,因此递归函数会非常复杂。

下面是一个没有递归的示例,它仅从 object 中删除 null 变量:

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);

这是一个没有递归的例子。如果你想让它在多维数组上工作,你需要编写递归程序。@MB34 - Joas
就像我之前所说的,我已经在尝试中尝试过类似的东西了。 - MB34

0

真的没时间测试它,但是编辑:已经测试过了,在原始代码中有一个错误(使用了clean_iterable(NULL,$v);而不是clean_iterable(NULL,$v[$key]);),已经修复了,这似乎可以工作:

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接