我有两个JSON对象,我想比较他们的结构。我该怎么办?
这些对象是即时生成的,取决于动态内容。 这意味着对象总是不同,但大多数时候具有相同的结构。我希望能够在发生变化时发现变化。
示例:这两个对象应被视为相等,因为它们都具有相同的结构:index var和tags数组。
{
"index": 0,
"tags": [
"abc"
]
}
{
"index": 1,
"tags": [
"xyz"
]
}
思想?
答案 0 :(得分:8)
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沙箱”中查看结果:
另外,当模式与值不匹配时,您可以使用软件包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 ";
}
?>