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); ```