Convert PHP array to JSON tree

I have an 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 need to convert this array to a json object using 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.

+2
source share
3 answers

My decision:

 $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); 
+10
source

Here is the code to do what you need. It does not need the elements to be in the order of the parent and child elements in the array, but will be faster to complete if there are any.

Please study the comments to understand what the code does 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 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 children array $objectMap[$parentId]->children[] = $current; // Set the item 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 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); 
+4
source

My trick (I know the answer is accepted, but I worked on it, so I will send 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 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; } } 
+3
source

All Articles