将PHP数组转换为JSON树
我得到了以下格式的数组:将PHP数组转换为JSON树,php,json,parent-child,Php,Json,Parent Child,我得到了以下格式的数组: array( array('id' => 1, 'parent_id' => null, 'name' => 'lorem ipsum'), array('id' => 2, 'parent_id' => 1, 'name' => 'lorem ipsum1'), array('id' => 3, 'parent_id' => 1, 'name' => 'lorem ipsum2'),
array(
array('id' => 1, 'parent_id' => null, 'name' => 'lorem ipsum'),
array('id' => 2, 'parent_id' => 1, 'name' => 'lorem ipsum1'),
array('id' => 3, 'parent_id' => 1, 'name' => 'lorem ipsum2'),
array('id' => 4, 'parent_id' => 2, 'name' => 'lorem ipsum3'),
array('id' => 5, 'parent_id' => 3, 'name' => 'lorem ipsum4'),
array('id' => 6, 'parent_id' => null, 'name' => 'lorem ipsum5'),
);
我必须将此数组转换为具有以下样式的json对象:
var json = {
id: "1",
name: "loreim ipsum",
data: {},
children: [{
id: "2",
name: "lorem ipsum1",
data: {},
children: [{
id: "3",
name: "lorem ipsum2",
data: {},
children: [{
..............
我该怎么做?谢谢。以下是您需要的代码。它不需要项目在数组中按父-子顺序排列,但如果它们按父-子顺序排列,则完成速度会更快 请研究这些评论,以了解代码在做什么以及为什么;如果你还有问题,也要问他们
// Assume your array is $data
$root = new stdClass; // this is your root item
$objectMap = array(); // this holds objects indexed by their id
// Since we need to iterate over the array, but there may be no guarantee
// that an item's parent will be always encountered before the item itself,
// we loop as many times as needed, skipping items whose parent we have not
// yet seen. Hopefully we will see it later and be able to process these
// items in the next iteration.
while (!empty($data)) {
// Remember how many items there are when starting the loop
$count = count($data);
// Do the actual work!
foreach ($data as $key => $row) {
$parentId = $row['parent_id'];
if ($parentId === null) {
// We just met the root element
$current = $root;
}
else if (isset($objectMap[$parentId])) {
// We met an element with a parent that we have already seen
$current = new stdClass;
}
else {
// We met an element with an unknown parent; ignore it for now
continue;
}
// Put the current element on the map so that its children will
// be able to find it when we meet them
$objectMap[$row['id']] = $current;
// Add the item to its parent's children array
$objectMap[$parentId]->children[] = $current;
// Set the item's properties
$current->id = $row['id'];
$current->name = $row['name'];
$current->data = new stdClass; // always empty
$current->children = array();
// We successfully processed this, remove it (see why below!)
unset($data[$key]);
}
// OK, we looped over the array once. If the number of items has
// not been reduced at all, it means that the array contains only
// items whose parents do not exist. Instead of looping forever,
// let's just take what we are given and stop here.
if ($count == count($data)) {
break;
}
// If there are still items in $data, we will now iterate again
// in the hope of being able to process them in the next iteration
}
// All set! If $data is not empty now, it means there were items
// with invalid parent_ids to begin with.
$output = json_encode($root);
我的解决方案:
$data = array(
array('id' => 1, 'parent_id' => null, 'name' => 'lorem ipsum'),
array('id' => 2, 'parent_id' => 1, 'name' => 'lorem ipsum1'),
array('id' => 3, 'parent_id' => 1, 'name' => 'lorem ipsum2'),
array('id' => 4, 'parent_id' => 2, 'name' => 'lorem ipsum3'),
array('id' => 5, 'parent_id' => 3, 'name' => 'lorem ipsum4'),
array('id' => 6, 'parent_id' => null, 'name' => 'lorem ipsum5'),
);
$itemsByReference = array();
// Build array of item references:
foreach($data as $key => &$item) {
$itemsByReference[$item['id']] = &$item;
// Children array:
$itemsByReference[$item['id']]['children'] = array();
// Empty data class (so that json_encode adds "data: {}" )
$itemsByReference[$item['id']]['data'] = new StdClass();
}
// Set items as children of the relevant parent item.
foreach($data as $key => &$item)
if($item['parent_id'] && isset($itemsByReference[$item['parent_id']]))
$itemsByReference [$item['parent_id']]['children'][] = &$item;
// Remove items that were added to parents elsewhere:
foreach($data as $key => &$item) {
if($item['parent_id'] && isset($itemsByReference[$item['parent_id']]))
unset($data[$key]);
}
// Encode:
$json = json_encode($data);
我的看法(我知道一个答案已经被接受,但我一直在努力,所以我要发布id=p)
//测试数据
$data=数组(
数组('id'=>1,'parent_id'=>null,'name'=>lorem ipsum'),
数组('id'=>2,'parent_id'=>1,'name'=>'lorem ipsum1'),
数组('id'=>3,'parent_id'=>1,'name'=>'lorem ipsum2'),
数组('id'=>4,'parent_id'=>2,'name'=>'lorem ipsum3'),
数组('id'=>5,'parent_id'=>3,'name'=>'lorem ipsum4'),
数组('id'=>6,'parent_id'=>null,'name'=>'lorem ipsum5'),
);
//随机化,因为数据可能不是自上而下的顺序
洗牌(数据);
//解析并检查结果
$builder=newtreebuilder($data);
回显“”,打印($builder->getTree()),“”;
类树生成器
{
受保护的$leaftindex=array();
受保护的$tree=array();
受保护的$stack;
函数构造($data)
{
$this->stack=$data;
while(计数($this->stack))
{
$this->branchify(数组移位($this->stack));
}
}
受保护功能分支(&$leaf)
{
//根水平叶?
如果(null==$leaf['parent\u id'])
{
$this->addLeaf($this->tree,$leaf);
}
//我们找到这片叶子的父母了吗?
else if(isset($this->leaveindex[$leaf['parent\u id']]))
{
$this->addLeaf($this->leaveindex[$leaf['parent_id']]['children'],$leaf);
}否则{
//不,把它放回堆栈上
$this->stack[]=$leaf;
}
}
受保护的函数addLeaf(&$branch,$leaf)
{
//将叶子添加到树枝上
$branch[]=数组(
'id'=>$leaf['id']
,'name'=>$leaf['name']
,“数据”=>新的stdClass
,'children'=>array()
);
//存储一个引用,以便稍后进行O(1)查找
$this->leaveindex[$leaf['id']]=&$branch[count($branch)-1];
}
受保护的函数addChild($branch,$leaf)
{
$this->leaveindex[$leaf['id']]&=$branch['children'][]=$leaf;
}
公共函数getTree()
{
返回$this->tree;
}
}
这对我不起作用-即使在修复了第38行的bug之后$objectMap[$parentId]->children[]=$current代码>修复了第38行(它是一个对象,不是数组)和第35行(设置$current=new stdClass
,重构后的遗留问题)上的愚蠢错误。现在可以了,谢谢你指出错误。我不知道你的最终数据应该是什么样子。在您的示例数据中,项目1和6都没有父项,但是您的示例输出被设计为只有一个根元素。JSON可以有多个根元素,结果只是示例。不-不是以您在这里定义它的方式。“根元素”在这里只是概念性的东西。您不能这样做var json={“id”:1,“id”:6}代码>并得到您想要的,因为您将得到{“id”:6}
。然而,如果您的“根”是一个数组(而不是一个对象),那么这将起作用-即,var json=[{“id”:1},{“id”:6}]
// Test data
$data = array(
array('id' => 1, 'parent_id' => null, 'name' => 'lorem ipsum'),
array('id' => 2, 'parent_id' => 1, 'name' => 'lorem ipsum1'),
array('id' => 3, 'parent_id' => 1, 'name' => 'lorem ipsum2'),
array('id' => 4, 'parent_id' => 2, 'name' => 'lorem ipsum3'),
array('id' => 5, 'parent_id' => 3, 'name' => 'lorem ipsum4'),
array('id' => 6, 'parent_id' => null, 'name' => 'lorem ipsum5'),
);
// Randomize, because the data may not be in a top-down order
shuffle( $data );
// Parse and inspect the result
$builder = new TreeBuilder( $data );
echo '<pre>', print_r( $builder->getTree() ), '</pre>';
class TreeBuilder
{
protected $leafIndex = array();
protected $tree = array();
protected $stack;
function __construct( $data )
{
$this->stack = $data;
while( count( $this->stack ) )
{
$this->branchify( array_shift( $this->stack ) );
}
}
protected function branchify( &$leaf )
{
// Root-level leaf?
if ( null === $leaf['parent_id'] )
{
$this->addLeaf( $this->tree, $leaf );
}
// Have we found this leaf's parent yet?
else if ( isset( $this->leafIndex[$leaf['parent_id']] ) )
{
$this->addLeaf( $this->leafIndex[$leaf['parent_id']]['children'], $leaf );
} else {
// Nope, put it back on the stack
$this->stack[] = $leaf;
}
}
protected function addLeaf( &$branch, $leaf )
{
// Add the leaf to the branch
$branch[] = array(
'id' => $leaf['id']
, 'name' => $leaf['name']
, 'data' => new stdClass
, 'children' => array()
);
// Store a reference so we can do an O(1) lookup later
$this->leafIndex[$leaf['id']] = &$branch[count($branch)-1];
}
protected function addChild( $branch, $leaf )
{
$this->leafIndex[$leaf['id']] &= $branch['children'][] = $leaf;
}
public function getTree()
{
return $this->tree;
}
}