PHP-比较两个JSON对象的结构
我有两个JSON对象,我想比较它们的结构。我怎么做 这些对象是动态生成的,取决于动态内容。 这意味着对象总是不同的,但大多数时候都有相同的结构。我希望能够捕获发生的更改 示例:这两个对象应视为相等,因为它们都具有相同的结构:索引变量和标记数组PHP-比较两个JSON对象的结构,php,json,object,Php,Json,Object,我有两个JSON对象,我想比较它们的结构。我怎么做 这些对象是动态生成的,取决于动态内容。 这意味着对象总是不同的,但大多数时候都有相同的结构。我希望能够捕获发生的更改 示例:这两个对象应视为相等,因为它们都具有相同的结构:索引变量和标记数组 { "index": 0, "tags": [ "abc" ] } { "index": 1, "tags": [ "xyz" ] } 想法?有点粗糙,但你能理解 $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对象,但在继续之前我必须确定。我在当前的工作项目中使用了这个库——对于我的目的来说效果很好(需要一个差异)。我也用过这个软件包,效果很好。节省了我很多时间,谢谢!