将 PHP 数组转换为 JSON 树

发布于 2024-10-05 06:50:02 字数 911 浏览 2 评论 0原文

我有一个这种格式的数组:

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: [{
            ..............

我该怎么做?谢谢。

I have got a array in this format:

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'),
);

I have to convert this array to json object with this style:

var json = {  
    id: "1",  
    name: "loreim ipsum",  
    data: {},  
    children: [{  
        id: "2",  
        name: "lorem ipsum1",  
        data: {},  
        children: [{  
            id: "3",  
            name: "lorem ipsum2",  
            data: {},  
            children: [{
            ..............

How can i do this? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

临走之时 2024-10-12 06:50:02

我的解决方案:

$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);

My solution:

$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);
⊕婉儿 2024-10-12 06:50:02

这是执行您需要的代码。它不需要数组中的项目按父子顺序排列,但如果是的话,完成速度会更快。

请研究注释以了解代码的作用及其原因;如果您还有疑问,也请询问他们!

// 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);

Here's code to do what you need. It does not need the items to be in parent-children order in the array, but will finish faster if they are.

Please study the comments to understand what the code is doing and why; and if you still have questions, ask them too!

// 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);
陌伤ぢ 2024-10-12 06:50:02

我的看法(我知道答案已被接受,但我对此进行了研究,所以我要发布 id =P)

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

My take (I know an answer has been accepted, but I worked on this so I'm gonna post id =P)

// 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;
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文