PHP-比较两个JSON对象的结构

PHP-比较两个JSON对象的结构,php,json,object,Php,Json,Object,我有两个JSON对象,我想比较它们的结构。我怎么做 这些对象是动态生成的,取决于动态内容。 这意味着对象总是不同的,但大多数时候都有相同的结构。我希望能够捕获发生的更改 示例:这两个对象应视为相等,因为它们都具有相同的结构:索引变量和标记数组 { "index": 0, "tags": [ "abc" ] } { "index": 1, "tags": [ "xyz" ] } 想法?有点粗糙,但你能理解 $json

我有两个JSON对象,我想比较它们的结构。我怎么做

这些对象是动态生成的,取决于动态内容。 这意味着对象总是不同的,但大多数时候都有相同的结构。我希望能够捕获发生的更改

示例:这两个对象应视为相等,因为它们都具有相同的结构
:索引变量和标记数组

{
    "index": 0,
    "tags": [
        "abc"
    ]
}
{
    "index": 1,
    "tags": [
        "xyz"
    ]
}

想法?

有点粗糙,但你能理解

$json = '[
        {
            "index": 0,
            "tags": [
                "abc"
            ]
        },
        {
            "index": 1,
            "tags": [
                "xyz"
            ]
        },
        {
            "foo": 2,
            "bar": [
                "xyz"
            ]
        }]';

$array = json_decode($json, true);
$default = array_keys($array[0]);

$error = false;
$errors = array();
foreach ($array as $index => $result):
    foreach ($default as $search):
        if (!isset($result[$search])):
            $error = true;
            $errors[] = "Property '{$search}' at entry '{$index}' not found. ";
        endif;
    endforeach;
endforeach;

if ($error):
    echo 'Objects are not the same. ';
    foreach ($errors as $message):
        echo $message;
    endforeach;
endif;
返回:

对象不一样。在条目“2”处找不到属性“index”。在条目“2”处找不到属性“tags”


您可以将json字符串转换为php数组,然后使用array_diff($arr1,$arr2)函数将新创建的数组与另一个数组进行比较 结果是一个数组,其中包含第一个数组中的元素,而另一个数组中不存在这些元素

例如:

<?php 
    $array1 = '{"name":"myname","age":"40"}';
    //convert the obtained stdclass object to an array
    $array1 = (array) json_decode($array1); 



    $array2 = array("name"=>"myname123","age"=>10);

    print_r($array2);

    $result_array = array_diff($array1,$array2);


    if(empty($result_array[0])){     
        echo "they have the same structure ";
    }



?>

你指的是结构,比如模型数组,比如:

array ( 'index' => int, 'tags' =>  array() )

如果这就是你想要得到的,试试这个

$arr1 = array (
    array (
        'index' => 0,
        'tags' =>  ['abc']
    ),
    array (
        'index' => 1,
        'tags' =>  ['xyz']
    ),
    array (
        'index' => 2,
        'tags' =>  ['xyz'],
        'boom' =>  'granade'
    ),
    array (
        'index' => 3,
        'tags' =>  'xyz'
    )
);

$holder = array();

$model  = array ('index' => 0, 'tags' => array());

for ($i = 0;$i < count($arr1); $i++)
{
    $holder = array_diff(array_merge_recursive($arr1[$i], $model), $model);

    if (!empty($holder))
    {
        echo "different structure<br>";
    }
    else
    {
        echo "same structure<br>";

        // for further validation
        /*
        $keys = array_keys($model);

        if (is_int($arr1[$i][$keys[0]]) && is_array($arr1[$i][$keys[1]]))
            echo "same structure<br>";
        else
            echo "different structure<br>";
        */
    }

}
##您可以使用这个php库## TreeWalker在php中是一个简单而简单的API
(我开发了这个库,希望对您有所帮助)

它提供了两种方法
1-获取json差异
2-编辑json值(递归)

此方法将返回json1和json2之间的差异

$struct1 = array("casa"=>1, "b"=>"5", "cafeina"=>array("ss"=>"ddd"), "oi"=>5);
$struct2 = array("casa"=>2, "cafeina"=>array("ss"=>"dddd"), "oi2"=>5);

//P.s
print_r($treeWalker->getdiff($struct1, $struct2))

{
    new: {
        b: "5",
        oi: 5
    },
    removed: {
        oi2: 5
    },
    edited: {
        casa: {
          oldvalue: 2,
          newvalue: 1
        },
        cafeina/ss: {
          oldvalue: "dddd",
          newvalue: "ddd"
        }
    },
    time: 0
}

你可以尝试使用这个软件包

示例:这两个对象应该被视为相等的,因为它们都具有相同的结构:索引变量和标记数组

{
    "index": 0,
    "tags": [
        "abc"
    ]
}
{
    "index": 1,
    "tags": [
        "xyz"
    ]
}
您可以创建如下“php匹配器模式”:

{
    "index": "@integer@",
    "tags": "@array@.repeat(\"@string@\")"
}
然后将JSON与此模式匹配。如果您有2个JSON,并且两者都匹配此模式,则根据您上面对相等的定义,这意味着它们是“相等的”

请参阅“php matcher sandbox”中的结果,了解您给出的示例JSON:

另外,当模式与值不匹配时,您可以使用包(如果您有phpunit,那么应该已经有了这个包)来生成一个diff

例如:

use SebastianBergmann\Diff\Differ;
use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;

...
    $valueToCheck = '{
        "foo": 0,
        "bar": {"one": 1, "two": "2"}
    }';
    $expectedValuePattern = '{
        "foo": "@integer@",
        "bar": {"one": 1, "two": 2}
    }';

    if (!$matcher->match($valueToCheck, $expectedValuePattern)) {
        $differ = new Differ(
            new UnifiedDiffOutputBuilder(
                "Json value is not matching expected format:\n",
                true
            )
        );
        $diffOutput = $differ->diff(
            \json_encode(\json_decode($expectedValuePattern, true), JSON_PRETTY_PRINT),
            \json_encode(\json_decode($valueToCheck, true), JSON_PRETTY_PRINT)
        );

        var_dump(
            $diffOutput
            . "\n".$matcher->getError()."\n"
        );
    } else {
        var_dump('OK');
    }
它将打印:

Json value is not matching expected format:
@@ -1,7 +1,7 @@
 {
-    "foo": "@integer@",
+    "foo": 0,
     "bar": {
         "one": 1,
-        "two": 2
+        "two": "2"
     }
 }

带有diff的消息对于更大的JSON快速查看哪个元素不匹配尤其有用

在该软件包的自述中查看更多使用方法-尤其是:

该包非常适合在自动测试(例如:phpunit)中使用,以断言API响应中的JSON是否正确等-考虑到在集成测试中,经常有许多id、uuid、datetime等在每次测试执行时发生变化-如数据库生成的id等


我希望它有帮助:)

那么您想检查对象1是否与对象2具有相同的字段?是的,完全正确。我试图使用RecursiveArrayIterator::hasChildren()来只迭代叶子,但这个解决方案在我看来并不优雅。也许有人知道更好的方法?@Boarking,你让它工作了吗?也许有用?这里的问题是默认数组。我如何生成它?我只有两个JSON对象。array_keys()也是一个不好的选项,因为它不是递归的。我的实际对象非常大,有许多嵌套级别。我必须能够比较每件事。难道不可能期望某种结构吗?据我所知,要有效地做到这一点,你需要有所期待。我不知道我在期待什么。我只知道我有两个可能相同的JSON对象,但在继续之前我必须确定。我在当前的工作项目中使用了这个库——对于我的目的来说效果很好(需要一个差异)。我也用过这个软件包,效果很好。节省了我很多时间,谢谢!