Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display JSON/YAML hierarchy as a tree in HTML?

I have YAML data that looks sort of like this, but ~150k of it:

---
all:
  foo: 1025
  bar:
    baz: 37628
    quux:
      a: 179
      b: 7

...or the same thing in JSON:

{"all":{"bar":{"baz":"37628","quux":{"a":"179","b":"7"}},"foo":"1025"}}

I want to present this content in an expandable JavaScripty HTML tree view (examples: 1, 2) to make it easier to explore. How do I do this?

I guess what I really want to figure out is how to take this YAML/JSON data, and automatically display it as a tree (with hash keys sorted alphabetically). So far, I've been tussling with YUI's tree view, but it doesn't accept straight JSON, and my feeble attempts to massage the data into something useful don't seem to be working.

Thanks for any help.

like image 646
Anirvan Avatar asked Oct 28 '08 19:10

Anirvan


3 Answers

You can convert your JSON data to nicely nested DIVs with this. I haven't tested it with a wide number of datasets, but it seems to work.

function renderJSON(obj) {
    'use strict';
    var keys = [],
        retValue = "";
    for (var key in obj) {
        if (typeof obj[key] === 'object') {
            retValue += "<div class='tree'>" + key;
            retValue += renderJSON(obj[key]);
            retValue += "</div>";
        } else {
            retValue += "<div class='tree'>" + key + " = " + obj[key] + "</div>";
        }

        keys.push(key);
    }
    return retValue;
}
like image 83
Diodeus - James MacFarlane Avatar answered Nov 02 '22 14:11

Diodeus - James MacFarlane


I finally came up with a super-elegant way to do this in about 5 lines of code, based on the fact that the simple YAML looks a lot like Markdown.

We're starting off with this:

---
all:
  foo: 1025
  bar:
    baz: 37628
    quux:
      a: 179
      b: 7

Use regexps (in this case, in Perl) to remove the starting ---, and put hyphens before the key on each line:

$data =~ s/^---\n//s;
$data =~ s/^(\s*)(\S.*)$/$1- $2/gm;

Voila, Markdown:

- all:
  - foo: 1025
  - bar:
    - baz: 37628
    - quux:
      - a: 179
      - b: 7

Now, just run it through a Markdown processor:

use Text::Markdown qw( markdown );
print markdown($data);

And you get an HTML list -- clean, semantic, backwards-compatible:

<ul>
    <li>all:
        <ul>
            <li>foo: 1025</li>
            <li>bar:</li>
            <li>baz: 37628</li>
            <li>quux:
                <ul>
                    <li>a: 179</li>
                    <li>b: 7</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

YUI Treeview can enhance existing lists, so we wrap it all up:

<html>
<head>
    <!-- CSS + JS served via YUI hosting: developer.yahoo.com/yui/articles/hosting/ -->
    <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.6.0/build/treeview/assets/skins/sam/treeview.css">
    <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/treeview/treeview-min.js"></script>
</head>
<body>
    <div id="markup" class="yui-skin-sam">
        <!-- start Markdown-generated list -->
        <ul>
            <li>all:
                <ul>
                    <li>foo: 1025</li>
                    <li>bar:</li>
                    <li>baz: 37628</li>
                    <li>quux:
                        <ul>
                            <li>a: 179</li>
                            <li>b: 7</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
        <!-- end Markdown-generated list -->
    </div>
    <script type="text/javascript">
        var treeInit = function() {
            var tree = new YAHOO.widget.TreeView("markup");
            tree.render();
        };
        YAHOO.util.Event.onDOMReady(treeInit);
    </script>
</body>
</html>

So this all works out to about 5 lines of code (turn YAML into Markdown, turn Markdown into an HTML list, and place that HTML list inside a template HTML file. The generated HTML's progressively-enhanced / degradable, since it's fully viewable on non-JavaScript browsers as a plain old list.

like image 9
Anirvan Avatar answered Nov 02 '22 14:11

Anirvan


Version 2.6 of YUI's TreeView now does take a JavaScript object but not in this format and won't sort it automatically. You would have to use YUI's JSON utility to convert it to an actual JavaScript which you will have to traverse. Your sample will have to be converted to something like this:

{label:"all", children[
    {label:"bar", children:[
        {label:"baz: 37628"},
        {label:"quux", children[
            {label:"a: 179"},
            {label:"b: 7"}
        ]},
        {label:"foo: 1025"}
    ]}
]}

I've probably missing some comma or something. Your incoming data might not be sorted so you will have to sort each array. Then, you just need to pass this object as the second argument to the TreeView constructor and the tree should appear.

like image 1
user32225 Avatar answered Nov 02 '22 13:11

user32225