This question may be subjective, but based on my experience, there is a more effective approach:
If you are using d3, chances are you are implementing something similar to this:
d3.selectAll('div')
.data(entities)
.enter()
.append('div')
...
The key consideration here is what constitutes your 'entities'. Are they all countries in the world? Or perhaps countries along with regions and the entire world? Alternatively, do your views only display countries within a selected region without including the region itself?
Unless the proposed JSON structure aligns perfectly with how entities are meant to be displayed, you will likely need to manipulate arrays extensively through concatenation and filtering to consolidate them into a single entities array for binding. While this approach might work, it could introduce unnecessary coupling between your code and data structure.
In my experience, maintaining a flat hierarchy, similar to that in an excel file, tends to be the most flexible and straightforward coding-wise. Rather than embedding regions into the hierarchy, keep them in a single, flat array like this:
{
"immigration": [
{
"name": "All Countries"
"values: [
{ "Year": ..., "value": ... },
{ "Year": ..., "value": ... },
...
]
},
{
"name": "Africa"
"values: [
{ "Year": ..., "value": ... },
{ "Year": ..., "value": ... },
...
]
},
{
"name": "Eastern Africa"
"continent": "Africa"
"values": [
{ "Year": ..., "value": ... },
{ "Year": ..., "value": ... },
...
]
},
// More country entries
]
}
Despite being flat, this array retains a hierarchical structure via properties like region
and sub-region
.
To extract desired countries/regions, simple filtering can be employed instead of navigating the proposed hierarchy:
var africanEntities = data.immigration.filter(function(country) {
return country.continent == "Africa";
}); // Includes the region "East Africa"
var justCountries = data.immigration.filter(function(country) {
return country.continent != null && country.region != null;
});
In addition, utilizing d3's d3.nest()
function can effortlessly transform flat data into a hierarchical format:
var countriesByContinent = d3.nest()
.key(function(d) { return d.continent; })
.map(data.immigration);
var africanEntities = countriesByContinent['Africa'];
Hopefully, this provides some clarity...