I have content pages in the database (using nested sets) and I need to show it by jQuery jsTree plugin. It's need to return JSON with data like this:
[
{
data: 'node1Title',
children: [
{
data: 'subNode1Title',
children: [...]
},
{
data: 'subNode2Title',
children: [...]
}
]
},
{
data: 'node2Title',
children: [...]
}
]
What I need for do it?
I can transform an array of hashes to JSON but I don't understand how to generate an array.
Sample data:
**'pages'table**
id parent_id level lkey rkey name
1 0 1 1 14 index
2 1 2 2 7 info
3 1 2 8 13 test
4 2 3 3 4 about
5 2 3 5 6 help
6 3 3 9 10 test1
7 3 3 11 12 test2
I need to get:
[
{
data: 'index',
children: [
{
data: 'info',
children: [
{
data: 'about'
},
{
data: 'help',
}
]
},
{
data: 'test',
children: [
{
data: 'test1'
},
{
data: 'test2'
}
]
}
]
}
]
I had exactly the same problem and here is what I wrote in Perl to convert my nested set tree into a JSON object for jsTree plugin (I'm using DBIx::Tree::NestedSet to access the MySQL database tree). I know my code is ugly from a Perl perspective, but it works for me.
sub get_json_tree {
my $json = '[';
my $first = 1;
my $last_level = 1;
my $level = 1;
my $tree = DBIx::Tree::NestedSet->new(dbh => $dbh);
my $ancestors = $tree->get_self_and_children_flat(id => $tree->get_root);
foreach (@{$ancestors}) {
my $name = $_->{'name'};
$last_level = $level;
$level = $_->{'level'};
if ($level > $last_level) {
$json .= ',' if ($json =~ /}$/);
} elsif ($level < $last_level) {
$json .= ']}';
for (my $i = 0; $i < $last_level - $level; $i++) {
$json .= ']}';
}
$json .= ',';
} elsif ($level == $last_level && !$first) {
$json .= ']},';
}
$json .= '{"attr":{"id":'.$_->{'id'}.',"rel":"folder"},"data":"'.$name.'","children":[';
$first = 0;
}
$json .= ']}';
for (my $i = 1; $i < $level; $i++) {
$json .= ']}';
}
$json .= ']';
return $json;
}
I'm looking for it. Perhaps DataTable plugin examples offer a solution. I'm looking on the plugin directory /examples/server_side/scripts/ssp.class.php. You can download it here.
Take a look about simplest way of using it at "Server-side script" label in this documentation.
This is very simple. You need to write a recursive function. I wrote it in Perl. $list - this is your array sorted by 'left_key'.
sub make_tree {
my $list = shift;
my @nodes;
while (my $node = shift @$list) {
if (@$list and $node->{level} < $list->[0]{level}) {
$node->{data} = make_tree($list);
push @nodes, $node;
}
last if @$list and $node->{level} > $list->[0]{level};
}
return \@nodes;
}
my $hash = make_tree($list);
Recently I was looking for a similar solution. I didn't find this until after posting my own question. The final code I posted on question I think would answers your question nicely.
I am using the following code with a modified version of DBIx::Tree::NestedSet. I use this code to create a JSON output of the nested sets tree.
Convert a flat datastructure into a tree
sub get_jsonTree {
my ($array_of_hashes_ref) = @_;
my $roots;
my %recs_by_name;
my %children_by_parent_name;
my %count;
for my $row (@$array_of_hashes_ref) {
my $name = $row->{position_id};
my $parent_name = $row->{placement_id};
my $rec = {
name => $name,
};
## Added to loop through all key,value pairs and add them to $rec
while ( my ($key, $value) = each(%$row) ) {
$rec->{$key} = $value;
}
##Added To Count Child Nodes
$count{$parent_name} = 0 if (!$count{$parent_name});
$rec->{'child_count'} = $count{$parent_name};
$count{$parent_name}++;
push @{ $children_by_parent_name{$parent_name // 'root'} }, $rec;
$recs_by_name{$name} = $rec;
}
$roots = delete($children_by_parent_name{root}) || [];
for my $name (keys(%children_by_parent_name)) {
my $children = $children_by_parent_name{$name};
if ( my $rec = $recs_by_name{$name} ) {
$rec->{children} = $children;
} else {
$util{'test'} .= "Parent $name doesn't exist.\n<BR>";
push @$roots, @$children;
}
}
use JSON;
my $json_str = encode_json(@{$roots}[0]);
return $json_str;
}
my $array_of_hashes_ref = [
{ position_id => 123, placement_id => undef },
{ position_id => 456, placement_id => 123 },
{ position_id => 789, placement_id => 123 },
# ...
];
my $json_str = &get_jsonTree($array_of_hashes_ref);