billgajen
billgajen

Reputation: 153

Node: How to restructure nested JSON data getting and organize reusable?

Using a Node request module, I am getting JSON data through an URL. The JSON file is nested in multiple levels and not organized in a way you can reuse. Current JSON looks like this:

{
  "data": {
    "series": {
      "brochure_image": "range.jpg",
      "background_image": "range.jpg",
      "Model 1": {
        "medium_images": "Model_1.png",
        "brand": "Tesla",
        "Model 101": {
          "medium_images": "Model_101.png",
          "brochure_image": "Model_101.png",
        },
        "Model 102": {
          "medium_images": "Model_102.png",
          "brochure_image": "Model_102.png",
        }
      },
      "Model 2": {
        "medium_images": "Model_2.png",
        "brand": "Tesla",
        "Model 201": {
          "medium_images": "Model_201.png",
          "brochure_image": "Model_201.png",
        }
      }
    }
  }
}

I want to restructure so I can easily access the data from the front end. I want to change like this:

[
  {
    "series":"Model 1",
    "model": [
      {
        "modelName": "Model 101",
        "medium_images": "Model_101.png",
        "brochure_image": "Model_101.png"
      },
      {
        "modelName": "Model 102",
        "medium_images": "Model_102.png",
        "brochure_image": "Model_102.png"
      }
    ] 
  }
  {
    "series":"Model 2",
    "model": [
      {
        "modelName": "Model 201",
        "medium_images": "Model_101.png",
        "brochure_image": "Model_101.png"
      }
    ] 
  }
]

How can I do this? My node server.js getting part looks like this:

const dataUrl = "http://example.com/data/series-data.json";

// API
app.get("/api/getSeriesData", (req, res) => {
    request.get(dataUrl, (error, response, body) => {
        var json = JSON.parse(body);
        var seriesObj = json.data.series;
        var seriesArr = [];

        for (var series in seriesObj) {

            if (seriesObj.hasOwnProperty(series)) {
                seriesArr.push({"series": series, "model": seriesObj[series]});
            }
        }
        res.send(seriesArr);
    });
});

Upvotes: 0

Views: 982

Answers (2)

Naren Murali
Naren Murali

Reputation: 56462

Here is my solution.

We can remove the unwanted keys in the object then loop through the object properties and add them to the array.

Please go through the snippet and let me know if you face any issues or doubts.

var data = {
  "data": {
    "series": {
      "brochure_image": "range.jpg",
      "background_image": "range.jpg",
      "Model 1": {
        "medium_images": "Model_1.png",
        "brand": "Tesla",
        "Model 101": {
          "medium_images": "Model_101.png",
          "brochure_image": "Model_101.png",
        },
        "Model 102": {
          "medium_images": "Model_102.png",
          "brochure_image": "Model_102.png",
        }
      },
      "Model 2": {
        "medium_images": "Model_2.png",
        "brand": "Tesla",
        "Model 201": {
          "medium_images": "Model_201.png",
          "brochure_image": "Model_201.png",
        }
      }
    }
  }
};
var output = [];
delete data.data.series.brochure_image
delete data.data.series.background_image
for (k in data.data.series) {
  var temp = [];
  delete data.data.series[k].medium_images;
  delete data.data.series[k].brand;
  for (j in data.data.series[k]) {
    temp.push({
      modelName: j,
      medium_images: data.data.series[k][j].medium_images,
      brochure_image: data.data.series[k][j].brochure_image
    });
  }
  output.push({
    "series": k,
    model: temp
  });
}
console.log(output);
 .as-console {
 height: 100%;
}
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

Upvotes: 1

Titus
Titus

Reputation: 22474

You can do something like this:

var obj = {
  "data": {
    "series": {
      "brochure_image": "range.jpg",
      "background_image": "range.jpg",
      "Model 1": {
        "medium_images": "Model_1.png",
        "brand": "Tesla",
        "Model 101": {
          "medium_images": "Model_101.png",
          "brochure_image": "Model_101.png",
        },
        "Model 102": {
          "medium_images": "Model_102.png",
          "brochure_image": "Model_102.png",
        }
      },
      "Model 2": {
        "medium_images": "Model_2.png",
        "brand": "Tesla",
        "Model 201": {
          "medium_images": "Model_201.png",
          "brochure_image": "Model_201.png",
        }
      }
    }
  }
};

var result = [];
Object.keys(obj.data.series).forEach(key => {
  if(key.indexOf("Model") === 0){
      var o = {series: key, model:[]};
      Object.keys(obj.data.series[key]).forEach(k => {
        if(k.indexOf("Model") === 0){
            o.model.push({modelName: k, medium_image: obj.data.series[key][k].medium_image, brochure_image: obj.data.series[key][k].brochure_image});
        }
      });
    result.push(o);
  }
});

console.log(result);

What this does is to loop through all the properties of the .data.series and data.series[MODEL NAME] and only consider those values of which property name starts with Model. If not all the values that you're interested in have their property name start with Model, this approach won't work. In those cases, you'll probably have to use a negative assertion (check if their property name isn't one of the known ones you're not interested in).

Upvotes: 2

Related Questions