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

时间:2015-08-17 08:22:57

标签: php json object

我有两个JSON对象,我想比较他们的结构。我该怎么办?

这些对象是即时生成的,取决于动态内容。 这意味着对象总是不同,但大多数时候具有相同的结构。我希望能够在发生变化时发现变化

示例:这两个对象应被视为相等,因为它们都具有相同的结构:index var和tags数组。

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

思想?

5 个答案:

答案 0 :(得分:8)

##您可以使用此库TreeWalker php。##

TreeWalker是一个简单的小型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
}

答案 1 :(得分:1)

这有点粗糙,但是你得到了照片;

$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”处的属性“索引”。找不到条目“2”处的属性“标签”。

答案 2 :(得分:0)

你的意思是结构,就像模型数组一样:

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>";
        */
    }

}

示例输出:

same structure
same structure
different structure
different structure

答案 3 :(得分:0)

您可以尝试使用软件包https://github.com/coduo/php-matcher

  

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

您可以像这样创建“ php-matcher模式”:

{
    "index": "@integer@",
    "tags": "@array@.repeat(\"@string@\")"
}

然后,您将JSON与该模式匹配。如果您有2个JSON且都匹配此模式,则表示根据上面对相等的定义,它们为“等于”

对于您提供的示例JSON,请在“ php-matcher沙箱”中查看结果:

Example 1 in sandbox

Example 2 in sandbox

另外,当模式与值不匹配时,您可以使用软件包https://github.com/sebastianbergmann/diff(如果有phpunit,应该已经拥有)来生成差异。

例如:

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快速查看哪个元素不匹配特别有用。

在该程序包的自述文件中查看更多使用方式-尤其是:

https://github.com/coduo/php-matcher#json-matching

https://github.com/coduo/php-matcher#json-matching-with-unbounded-arrays-and-objects

此包非常适合用于自动测试(例如:phpunit)中,以断言来自API响应的JSON是否正确等-考虑到在集成测试中,通常会有许多id,uuid,datetime等在每次测试中都会改变执行-例如数据库生成的ID等。

我希望这会有所帮助:)

答案 4 :(得分:-1)

您可以将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 ";
    }



?>