Reputation: 11
I'm trying to figure out the best way to transform some JSON data into the format requested for bootstrap-treeview. My initial thought was to create some sort of recursive function to go through and modify everything, but i'm having some real difficulty in achieving this. Any advice would be much appreciated!
Here a console log of the data returned by my service:
Object
England: Object
London: Object
Bayerische Staatsbibliothek: Object
Cod. arab. 1251: Array[1]
0: Object
key1: "adflkjadf",
key2: "adflkjadfk",
key3: "adlkfjadf",
__proto__: Object
length: 1
text: "Cod. arab. 1251"
__proto__: Array[0]
Cod. arab. 1252: Array[1]
Cod. arab. 1253: Array[1]
Cod. arab. 1254: Array[1]
Cod. arab. 1255: Array[1]
Cod. arab. 1256: Array[1]
Cod. arab. 1257: Array[1]
Cod. arab. 1258: Array[1]
Cod. arab. 1259: Array[1]
Cod. arab. 1260: Array[1]
Germany: Object
Munich: Object
Bayerische Staatsbibliothek: Object
Cod. arab. 1251: Array[1]
0: Object
key1: "adflkjadf",
key2: "adflkjadfk",
key3: "adlkfjadf",
__proto__: Object
length: 1
text: "Cod. arab. 1251"
__proto__: Array[0]
Cod. arab. 1252: Array[1]
Cod. arab. 1253: Array[1]
Cod. arab. 1254: Array[1]
Cod. arab. 1255: Array[1]
Cod. arab. 1256: Array[1]
Cod. arab. 1257: Array[1]
Cod. arab. 1258: Array[1]
Cod. arab. 1259: Array[1]
Cod. arab. 1260: Array[1]
Here's the format the the boostrap-treeview needs:
var tree = [
{
text: "Parent 1",
nodes: [
{
text: "Child 1",
nodes: [
{
text: "Grandchild 1"
},
{
text: "Grandchild 2"
}
]
},
{
text: "Child 2"
}
]
},
{
text: "Parent 2"
},
{
text: "Parent 3"
},
{
text: "Parent 4"
},
{
text: "Parent 5"
}
];
Here's my attempt at a recursive function to accomplish this:
function format_for_treeview(node) {
for (var key in node) {
// skip loop if the property is from prototype
if (!node.hasOwnProperty(key)) continue;
if (typeof node === 'object') {
format_for_treeview(node[key]);
if (Array.isArray(node)) {
node[key]['text'] = node[key]['bibliography_text'];
} else {
node[key]['text'] = key;
}
}
}
}
Upvotes: 1
Views: 3485
Reputation: 4064
If you need bootstrap treeview
and want parse an arbitrary JSON
data to its format. You can use this recursive function
. I just made a few changes on your original code.
function format_for_treeview(node) {
for (var key in node) {
// skip loop if the property is from prototype
if (!node.hasOwnProperty(key)) continue;
if (typeof node === 'object') {
format_for_treeview(node[key]);
if (Array.isArray(node)) {
node[key]['text'] = node[key]['bibliography_text'];
} else {
node[key]['text'] = key;
}
}
}
}
Changing this will work like you expected. ( See the code snippet below. )
function format_for_treeview(data, arr) {
for (var key in data) {
if(Array.isArray(data[key]) || data[key].toString() === "[object Object]") {
// when data[key] is an array or object
var nodes = [];
var completedNodes = completeNodes(data[key], nodes);
arr.push({ text: key, nodes: completedNodes });
} else {
// when data[key] is just strings or integer values
arr.push({ text: key + " : " + data[key] });
}
}
return arr;
}
var data = {
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
};
$(document).ready(function() {
function format_for_treeview(data, arr) {
for (var key in data) {
if (Array.isArray(data[key]) || data[key].toString() === "[object Object]") {
// when data[key] is an array or object
var nodes = [];
var completedNodes = format_for_treeview(data[key], nodes);
arr.push({
text: key,
nodes: completedNodes
});
} else {
// when data[key] is just strings or integer values
arr.push({
text: key + " : " + data[key]
});
}
}
return arr;
}
$("#my-treeview").treeview({
color: "#428bca",
expandIcon: "glyphicon glyphicon-stop",
collapseIcon: "glyphicon glyphicon-unchecked",
showTags: true,
data: format_for_treeview(data, [])
});
});
<link href="https://jonmiles.github.io/bootstrap-treeview/bower_components/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://jonmiles.github.io/bootstrap-treeview/js/bootstrap-treeview.js"></script>
<div id="my-treeview"></div>
You can customize the push
part to make the " key : value " more noticable by inserting HTML string between them like this below.
arr.push({ text: "<span class="key-stub"> + key + "</span>", nodes: completedNodes });
Personally, if you just need a feature that converts JSON
to a tree view, you don't have to struggle with this. Just consider using this one. No conversion is required.
Upvotes: 0
Reputation: 11
With help from the following link I discovered d3's nest() function does almost exactly what i needed. However, i did have to fork the d3.js file and rename the 'key' and 'values' key names in the nest()->entries() map function.
Additionally, I modified the service to return an array of objects instead of trying to do grouping inside the service.
var withText = jsondata.map(function(i) {
i['text'] = i['bibliography_text'];
return i;
});
var nestedData = d3.nest()
.key(function(d) { return d.country; })
.key(function(d) { return d.city; })
.entries(withText);
The resulting output gives me an array exactly like the var tree = [...]
listed above.
Upvotes: 0