Using JSON to Simplify Code


The Goal

In this section, you will understand how using JSON can simplify your D3.js code as well as your JavaScript code.

We will cover previous examples, how to bind JSON objects to the __data__ attribute and how we can use JSON to clean up the code for easier comprehension.


Previous Example of Three Circles

In the Using the SVG Coordinate Space section, we created and styled three circles using D3.js

 1var spaceCircles = [30, 70, 110];
 2
 3var svgContainer = d3.select("body").append("svg")
 4                                    .attr("width", 200)
 5                                    .attr("height", 200);
 6
 7var circles = svgContainer.selectAll("circle")
 8                          .data(spaceCircles)
 9                          .enter()
10                          .append("circle");
11
12var circleAttributes = circles
13                       .attr("cx", function (d) { return d; })
14                       .attr("cy", function (d) { return d; })
15                       .attr("r", 20 )
16                       .style("fill", function(d) {
17                         var returnColor;
18                         if (d === 30) { returnColor = "green";
19                         } else if (d === 70) { returnColor = "purple";
20                         } else if (d === 110) { returnColor = "red"; }
21                         return returnColor;
22                       });

Running the above JavaScript code in the JavaScript Console gaves us this:

Created three colored circles using D3.js in SVG Coordinate Space

This example used the data to set the cx, cy and style fill for each circle.

However, as you probably noticed, the cx and cy units were the same.

Also - perhaps more dangerous, was that the if statements had hard coded values.

Hard coded values are never a good idea, because if our data changes, then we would have to change our code in several places.


Binding JSON Objects to the __data__ Attribute

In the Data Structures D3.js Accepts section, we covered how we could use JavaScript JSON Objects in the Data Array we pass to D3.js.

Using our example above (the three circles) and the JSON notation, we could write our data array as follows:

 1var jsonCircles = [
 2  {
 3   "x_axis": 30,
 4   "y_axis": 30,
 5   "radius": 20,
 6   "color" : "green"
 7  }, {
 8   "x_axis": 70,
 9   "y_axis": 70,
10   "radius": 20,
11   "color" : "purple"
12  }, {
13   "x_axis": 110,
14   "y_axis": 100,
15   "radius": 20,
16   "color" : "red"
17}];

Note that we have moved our color from the if ... then functions in the D3.js code to our data.

This will not always be possible. For now, we will assume it is possible and deal with other cases later.

In doing this, we can now type the following into our JavaScript Console:

 1var jsonCircles = [
 2  {
 3   "x_axis": 30,
 4   "y_axis": 30,
 5   "radius": 20,
 6   "color" : "green"
 7  }, {
 8   "x_axis": 70,
 9   "y_axis": 70,
10   "radius": 20,
11   "color" : "purple"
12  }, {
13   "x_axis": 110,
14   "y_axis": 100,
15   "radius": 20,
16   "color" : "red"
17}];
18
19var svgContainer = d3.select("body").append("svg")
20                                    .attr("width", 200)
21                                    .attr("height", 200);
22
23var circles = svgContainer.selectAll("circle")
24                          .data(jsonCircles)
25                          .enter()
26                          .append("circle");

Which gives us this:

Using JSON to generate three SVG circles

Which we can check in the console.log to see what data was bound to each of the three circles:

 1var jsonCircles = [
 2  {
 3   "x_axis": 30,
 4   "y_axis": 30,
 5   "radius": 20,
 6   "color" : "green"
 7  }, {
 8   "x_axis": 70,
 9   "y_axis": 70,
10   "radius": 20,
11   "color" : "purple"
12  }, {
13   "x_axis": 110,
14   "y_axis": 100,
15   "radius": 20,
16   "color" : "red"
17}];
18
19console.log(d3.select("body").append("svg").attr("width", 200).attr("height", 200).selectAll("circle").data(jsonCircles).enter().append("circle"));

This shows us that an object was bound to the __data__ attribute of the circle:

Used D3.js to attach JSON object to SVG Circle

Which is fantastic!

Before we had been able to bind a single number to the __data__ attribute. Now we have bound a JSON object to the __data__ attribute.

And because the object is bound to the __data__ attribute, it means that D3.js can use it within its operator and methods!


Use Bound JSON Objects to Alter SVG Elements

We will now use the bound JSON Objects in the __data__ attribute to alter the SVG Circles.

If you recall the Creating SVG Elements Based on Data section, we discussed the key to using the bound data, being the JavaScript function:

1function (d) { return d; }

If you recall the previous section Data Structures D3.js Accepts, we covered how JSON objects allow us to use their name/value pair to call specific data from them:

1var secretAgent = {
2  "name":"James Bond",
3  "drink":"dry martini - shaken, not stirred",
4  "number":"007"
5};
6
7secretAgent.number;
8// "007" is returned.

Combining these two pieces of knowledge, allows us to write the following in D3.js:

1function (d) { return d.name; }

Where name is the name associated with the specific name/value pair in the JSON Object.

In our case, using our jsonCircles JSON data array:

 1var jsonCircles = [
 2  {
 3   "x_axis": 30,
 4   "y_axis": 30,
 5   "radius": 20,
 6   "color" : "green"
 7  }, {
 8   "x_axis": 70,
 9   "y_axis": 70,
10   "radius": 20,
11   "color" : "purple"
12  }, {
13   "x_axis": 110,
14   "y_axis": 100,
15   "radius": 20,
16   "color" : "red"
17}];

We can write functions like the following:

1function (d) { return d.x_axis; }
2
3function (d) { return d.y_axis; }
4
5function (d) { return d.radius; }
6
7function (d) { return d.color; }

This leads to code with easier comprehension.

Which means we can write our earlier example as follows:

 1var jsonCircles = [
 2  { "x_axis": 30, "y_axis": 30, "radius": 20, "color" : "green" },
 3  { "x_axis": 70, "y_axis": 70, "radius": 20, "color" : "purple"},
 4  { "x_axis": 110, "y_axis": 100, "radius": 20, "color" : "red"}];
 5
 6var svgContainer = d3.select("body").append("svg")
 7                                    .attr("width", 200)
 8                                    .attr("height", 200);
 9
10var circles = svgContainer.selectAll("circle")
11                          .data(jsonCircles)
12                          .enter()
13                          .append("circle");
14
15var circleAttributes = circles
16                       .attr("cx", function (d) { return d.x_axis; })
17                       .attr("cy", function (d) { return d.y_axis; })
18                       .attr("r", function (d) { return d.radius; })
19                       .style("fill", function(d) { return d.color; });

Which gives us:

Created three circles with D3.js and JSON data

Bravo!

We cleaned up our code by removing the hardcoded if/then statements from our .style() operator.

We also made it easier to understand what the return d was actually returning.

We have now successfully used JSON to create D3.js Data Visualizations as well as used functions in the operators and methods to style our SVG elements.

If you found this D3 Tutorial helpful, you'll enjoy these FREE videos: