通过键在php中重构多维json
Posted
技术标签:
【中文标题】通过键在php中重构多维json【英文标题】:refactor multidimensional json in php by keys 【发布时间】:2021-12-19 21:58:06 【问题描述】:我正在做一个项目,我正在尝试通过 $keys 数组重构一个 json 对象 例如:
-
作为输入:
"message": "User Detail",
"code": 200,
"error": false,
"results":
"user":
"id": 2,
"name": "ali",
"country":
"id": 50,
"name": "EGY"
,
"access_token": "=PQLkHJYIXB2uKbCq4sXIjD2GpBU2o"
-
作为输入:$keys 数组
$kyes = [
'code',
'user'=>[
'id',
'country'=>['name']
]
]
期待回归:
"code": 200,
"user":
"id": 2,
"country":
"name": "egy",
我试过的代码:
public function filter_multidimensional(array $array, array $keys)
$val = [];
foreach ($array as $key => $value)
if (in_array($key,$keys))
$val[$key] = $value;
elseif (is_array($value))
$val[$key] = $this->filter_multidimensional($keys,$value);
return $val;
//-------
$this->filter_multidimensional($json,['code','user'=>['id','country'=>['name']]])
不幸的是输出:
更新 1
json 输入不是 const,所以我的代码必须适应。这就是我想要做的。
【问题讨论】:
【参考方案1】:感谢@404-not-found 他的代码很棒,但缺少一个小东西 在这段代码中
if (is_array($key))
$val[$objectKey] = filter_multidimensional($array, $key);
你仍然给 find 函数一个基本数组,它将返回它在 ['user'=>['id',"country"=>['id']]]
的情况下找到的第一个值,解决这个问题的方法是传递对象键的父数组
所以完整的代码将是
<?php
function filter_multidimensional(array $array, array $keys)
if (empty($keys) || empty($array))
return [];
$val = [];
// In the structure of $keys, both key and value are technically "keys".
// In the example `['code','user'=>['id']]`, 'code' and 'id' are both array *values*,
// while 'user' is a key.
//
// So, $objectKey is a search key which contains sub-keys, while $key is just a regular string.
foreach ($keys as $objectKey => $key)
// If $key is an array, then recursively search, and save the results to the $objectKey string.
if (is_array($key))
$val[$objectKey] = filter_multidimensional(findTill($array,$objectKey), $key);
// If the desired key exists, then save the value.
else if (array_key_exists($key, $array))
$val[$key] = $array[$key];
// Otherwise, $key is a string, but it does not exist at this level of $array,
// so search the next-level up in $array, and merge the results into this level of $val.
else
$val = array_merge($val, filter_multidimensional(nextLevel($array), [$key]));
return $val;
function findTill($array,$key)
if (array_key_exists($key, $array))
return $array[$key];
return findTill(nextLevel($array),$key);
/**
* Create an array that contains only the array values from $array.
*
* Eg: If given ['a' => '1', 'b' => ['foo' => '2'], 'c' => ['hello' => 'world']],
* then return ['foo' => '2', 'hello' => 'world']
*
* @param array $array
* @return array
*/
function nextLevel(array $array)
// Merge all of the array values together into one array
return array_reduce(
// Strip the keys
array_values(
// Filter to return only keys where the value is an array
array_filter(
$array,
function ($value)
return is_array($value);
)
),
'array_merge',
[]
);
//-------
$obj = [
"message" => "User Detail",
"code" => 200,
"error" => false,
"results" => [
"user" => [
"id" => 2,
"name" => "ali",
"country" => [
"id" => 50,
"name" => "EGY",
],
],
"access_token" => "=PQLkHJYIXB2uKbCq4sXIjD2GpBU2o",
],
];
$result = filter_multidimensional($obj,['code','user'=>['id','country'=>['id','name']],"access_token"]);
【讨论】:
【参考方案2】:我相信这种方法有效。我颠覆了你的逻辑,我没有搜索 $array
以查看其键是否与 $keys
中的任何一个匹配,而是递归搜索 $keys
以查看 $array
是否有任何匹配值。
function filter_multidimensional(array $array, array $keys)
if (empty($keys) || empty($array))
return [];
$val = [];
// In the structure of $keys, both key and value are technically "keys".
// In the example `['code','user'=>['id']]`, 'code' and 'id' are both array *values*,
// while 'user' is a key.
//
// So, $objectKey is a search key which contains sub-keys, while $key is just a regular string.
foreach ($keys as $objectKey => $key)
// If $key is an array, then recursively search, and save the results to the $objectKey string.
if (is_array($key))
$val[$objectKey] = filter_multidimensional($array, $key);
// If the desired key exists, then save the value.
else if (array_key_exists($key, $array))
$val[$key] = $array[$key];
// Otherwise, $key is a string, but it does not exist at this level of $array,
// so search the next-level up in $array, and merge the results into this level of $val.
else
$val = array_merge($val, filter_multidimensional(nextLevel($array), [$key]));
return $val;
/**
* Create an array that contains only the array values from $array.
*
* Eg: If given ['a' => '1', 'b' => ['foo' => '2'], 'c' => ['hello' => 'world']],
* then return ['foo' => '2', 'hello' => 'world']
*
* @param array $array
* @return array
*/
function nextLevel(array $array)
// Merge all of the array values together into one array
return array_reduce(
// Strip the keys
array_values(
// Filter to return only keys where the value is an array
array_filter(
$array,
function ($value)
return is_array($value);
)
),
'array_merge',
[]
);
//-------
$result = filter_multidimensional($obj,['code','user'=>['id','country'=>['name']]]);
【讨论】:
非常感谢,这真的很棒!!! ,只是一个小问题:我相信我们应该在设置值之前检查父键名>>检查一下:pastebin.com/embed_iframe/2iUksnFY 这里是问题的代码响应:pastebin.com/embed_iframe/QuZQLCac?theme=dark 有什么解决办法吗? ,【参考方案3】:您可以使用data_get
和data_set
的组合来获得您想要的。
稍微更改输入,使其更加一致。点符号是最简单的。
$array = [
"message" => "User Detail",
"code" => 200,
"error" => false,
"results" => [
"user" => [
"id" => 2,
"name" => "ali",
"country" => [
"id" => 50,
"name" => "EGY",
],
],
"access_token" => "=PQLkHJYIXB2uKbCq4sXIjD2GpBU2o",
],
];
$keys = [
'code' => 'code',
'user.id' => 'results.user.id',
'user.country.name' => 'results.user.country.name',
];
$results = [];
foreach ($keys as $set_position => $get_position)
data_set($results, $set_position, data_get($array, $get_position));
【讨论】:
感谢您的回答,这是一个非常好的答案,但是正如我在 update 1 中所说: 我不知道json
中的索引路径,它存在于 json 中(这是肯定的),但我必须遍历数组,直到找到 $key
我认为data_get
可以接受占位符。也许像'*'.$get_position
这样的东西可能有用以上是关于通过键在php中重构多维json的主要内容,如果未能解决你的问题,请参考以下文章