dani
dani

Reputation: 5000

Transforming JSON data from API into useful format?

I have an API that returns indicator data in this format:

[
    {
            "concept": "population",
            "year": 2012,
            "value": 9.5,
            "country-name": "Sweden",
    },
    {
            "concept": "education",
            "year": 2012,
            "value": 12,
            "country-name": "Sweden",
    },
    {
            "concept": "population",
            "year": 2012,
            "value": 5,
            "country-name": "Norway",
    },
    {
            "concept": "eduction",
            "year": 2012,
            "value": 12,
            "country-name": "Norway",
    }
]

Based on this, I typically need to group this by country and year to get something like:

var data = [
   {id : Sweden, population : 9.5, education: 12},
   {id : Norway, population : 5, education: 12},
]

Or just by country and year-values as an array:

var data = [
   {id : Sweden, values : [ { year : 2012, population : 9.5, education: 12 }, {...} ]},
   {id : Norway, values : [ { year : 2012, population : 5, education: 12 }, {...} ]},
]
  1. What JS libraries can help manage these common data transformations?
  2. Can you provide an example of doing the above (using a library or vanilla js)?

Upvotes: 0

Views: 66

Answers (3)

1983
1983

Reputation: 5963

You might find an object easier to work with than an array:

var data = {};
indicatordata.forEach(function(item){
    var country = item['country-name'];
    var year = item.year;
    data[country] = data[country] || {id: item['country-name'], values: {}};
    var values = data[country].values;
    values[year] = values[year] || {};
    values[year][item.concept] = item.value;
});

Upvotes: 0

saaj
saaj

Reputation: 25273

You can do it with D3. d3.nest and Array.prototype.reduce specifically. The code is declarative and easy to maintain.

var rawData = [
  {
    "concept": "population",
    "year": 2012,
    "value": 9.5,
    "country-name": "Sweden",
  },
  {
    "concept": "education",
    "year": 2012,
    "value": 12,
    "country-name": "Sweden",
  },
  {
    "concept": "population",
    "year": 2012,
    "value": 5,
    "country-name": "Norway",
  },
  {
    "concept": "eduction",
    "year": 2012,
    "value": 12,
    "country-name": "Norway",
  }
];

var data = d3.nest()
  .key(function(d)
  {
    return d['year'];
  })
  .key(function(d)
  {
    return d['country-name'];
  })
  .rollup(function(group)
  {
    return group.reduce(function(result, d)
    {
      result[d['concept']] = d['value'];
      return result;
    }, {});
  })
  .entries(rawData);

console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: -1

adeneo
adeneo

Reputation: 318322

You can do it yourself, just iterate and create whatever you need, something like

var data = [];

json.forEach(function(item) {
    var country = item['country-name'],
        match   = false,
        obj     = {}

    data.forEach(function(dataItem, i) {
        if (dataItem.id === country) {
            match = true;
            obj   = data[i];
        }
    });

    obj.id = country;
    obj[item.concept] = item.value;

    if (!match) data.push(obj)
});

FIDDLE

Upvotes: 2

Related Questions