Question

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.

Was it helpful?

Solution 2

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.

OTHER TIPS

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top