Render D3 graph from a string of JSON instead of a JSON file

d3.js, json

Solution

First, lets look at what `d3.json` does.

d3.json("/assets/flare.json", function(root) {
    // code that uses the object 'root'
});

This loads the file `/assets/flare.json` from the server, interprets the contents as JSON and passes the resulting object as the `root` argument to the anonymous function.

Where you already have a JSON object, you don't need to use the `d3.json` function - you can just use the object directly.

var root = {
   "name": "flare",
   "children": [
     ...
   ]
};
// code that uses the object 'root'

If the object is represented as a string, then you can use `JSON.parse` to get the object:

var myString = '{"name": "flare","children": [ ... ] }';
var root = JSON.parse(mystring);
// code that uses the object 'root'

Second, lets look at what `d3.layout.cluster` expects of your data. As per the docs:

... the default children accessor assumes each input data is an object with a children array ...

In other words, you data needs to be of the form:

var mystring = '{
    "name": "Product",
    "children": [
        {
            "name": "id",
            "type": "number",
            "description": "Product identifier",
            "required": true
        },
        ...
        {
            "name": "stock",
            "type": "object",
            "children": [
                {
                    "name: "warehouse",
                    "type": "number"
                },
                {
                    "name": "retail",
                    "type": "number"
                }
            ]
        }
    ]
}

Problem

I am trying to render the following Dendrogram from my Rails app: http://bl.ocks.org/mbostock/4063570 I have a model with many attributes, but I would like to manually nest those attributes and simply use string interpolation to build up my own JSON string, then pass that to d3 directly. Here is my code: ``` <%= javascript_tag do %> var width = 960, height = 2200; var cluster = d3.layout.cluster() .size([height, width - 160]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [d.y, d.x]; }); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(40,0)"); **d3.json("/assets/flare.json", function(root) {** var nodes = cluster.nodes(root), links = cluster.links(nodes); var link = svg.selectAll(".link") .data(links) .enter().append("path") .attr("class", "link") .attr("d", diagonal); var node = svg.selectAll(".node") .data(nodes) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) node.append("circle") .attr("r", 4.5); node.append("text") .attr("dx", function(d) { return d.children ? -8 : 8; }) .attr("dy", 3) .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) .text(function(d) { return d.name; }); }); d3.select(self.frameElement).style("height", height + "px"); <% end %> ``` Here is my (unminified) JSON string: ``` var mystring = '{ "name": "Product", "properties": { "id": { "type": "number", "description": "Product identifier", "required": true }, "name": { "type": "string", "description": "Name of the product", "required": true }, "price": { "type": "number", "minimum": 0, "required": true }, "tags": { "type": "array", "items": { "type": "string" } }, "stock": { "type": "object", "properties": { "warehouse": { "type": "number" }, "retail": { "type": "number" } } } } }'; ``` Things I've tried: minifying the JSON so it's inputted as just one line (no effect) running JSON.parse(mystring) on the string looking through the D3 documentation and and googling for a way to modify the following function to accept a string instead of a file path: ``` d3.json("/assets/flare.json", function(root) { var nodes = cluster.nodes(root), links = cluster.links(nodes); ```

Original source

Related problems