how to transform json data into table - javascript

I have the below api call that returns data in JSON:
https://xama-was-service.herokuapp.com/api/socialone/databoards/10042?1=2019-02-01T00:00:00.000Z&2=test
That returns data as below:
[
[
{
"Empid": 2326,
"Empname": "Sam Smith",
"AbsenceId": 12840,
"Comment": "a001t000004FQgHAAW",
"AbsenceStartDate": "2019-05-31T00:00:00.000Z",
"AbsenceEndDate": "2019-05-31T00:00:00.000Z",
"JobId": 400004,
"AbsenceRequestId": ""
},
{
"Empid": 3387,
"Empname": "Joe bloggs",
"AbsenceId": 12842,
"Comment": "a001t000004FK67AAG",
"AbsenceStartDate": "2019-06-06T00:00:00.000Z",
"AbsenceEndDate": "2019-06-10T00:00:00.000Z",
"JobId": 700004,
"AbsenceRequestId": ""
}
]
]
I would like to move this into excel and also power bi but i cannot transform it into a table?
Can anyone advise how to format the returned data into a table or what code to use on the original call to help with this?
ideal end product would be as below but not sure how to achieve?
Thanks.

This will parse your data into a comma delimited string (CSV).
You just need to separate each row element with a comma ,, and each row with a new line character \n. Excel knows this format, though sometimes you may need to use the text to columns function to let it know the data is comma delimited.
const data = [
[
{
"Empid": 2326,
"Empname": "Sam Smith",
"AbsenceId": 12840,
"Comment": "a001t000004FQgHAAW",
"AbsenceStartDate": "2019-05-31T00:00:00.000Z",
"AbsenceEndDate": "2019-05-31T00:00:00.000Z",
"JobId": 400004,
"AbsenceRequestId": ""
},
{
"Empid": 3387,
"Empname": "Joe bloggs",
"AbsenceId": 12842,
"Comment": "a001t000004FK67AAG",
"AbsenceStartDate": "2019-06-06T00:00:00.000Z",
"AbsenceEndDate": "2019-06-10T00:00:00.000Z",
"JobId": 700004,
"AbsenceRequestId": ""
}
]
]
window.generateCSV = function () {
let CSVData = ''
// set the column names
for (const value of Object.keys(data[0][0])) {
CSVData = CSVData.concat(value + ',')
}
CSVData = CSVData.slice(0, CSVData.length - 1)
CSVData = CSVData.concat('\n')
// parse the data
for (const tbl of data) {
for (const row of tbl) {
for (const value of Object.values(row)) {
CSVData = CSVData.concat(value + ',')
}
CSVData = CSVData.slice(0, CSVData.length - 2)
CSVData = CSVData.concat('\n')
}
}
document.getElementById("csvdata").innerText = CSVData
}
<input type="button" value="generateCSV" onclick="generateCSV()">
<div id="csvdata">
</div>
After saving the output string to a .txt or .csv through notepad, I can open in excel to get this.

Related

How can I extract object/key names from nested and varying JSON payload in a Postman Test script?

I am an old-school C++ programmer - trying to get to grips with Postman, JSON, REST APIs, etc, and struggling..
I am trying to write a Postman test to visualize some JSON response data - which I would like to show in a table format with some merged key names as column headings.
The problem is that the number of data items in a response can vary and the key names can also vary - depending on the input parameters.
So say, for the following JSON which has two data items:
{
"data": [
{
"input": [
{
"value": "ABC",
"identifierType": "a1"
}
],
"output": [
{
"value": "BT",
"identifierType": "b1",
"name": "BT GROUP",
"status": "Active",
"classification": "Ordinary"
}
]
},
{
"input": [
{
"value": "BCD",
"identifierType": "a1"
}
],
"output": [
{
"value": "EFG",
"identifierType": "b1",
"name": "SIEMENS",
"status": "Active",
"classification": "Ordinary"
}
]
}
]
}
I want to end up with a collection containing column headings that looks something like this:
[“Input value”, “Input identifierType”,“Output value”,“Output identifierType”,“Output name”,“Output status”,“Output classification”]
I can get part of the way with something like the following:
function parseData(response, host) {
const results = response.map(elem => (
[
elem.input[0].value,
elem.input[0].identifierType,
elem.output[0].value,
elem.output[0].identifierType,
elem.output[0].name,
elem.output[0].status,
elem.output[0].classification,
]
));
const headers = [];
for (const key in response[0].input[0]){
headers.push(`Input ${key}`)
}
for (const key in response[0].output[0]){
headers.push(`Output ${key}`)
}
return [results, headers]
}
This gives me the desired headers: [“Input value”, “Input identifierType”,“Output value”,“Output identifierType”,“Output name”,“Output status”,“Output classification”]
However, I want to make this more general i.e. not have to specify input[0] and output[0] in the for loops - as these key names could differ for different query responses.
I did ask this question on the Postman forums and someone helpfully provided a code snippet that allows me to extract the 'input' and 'output' names.
for (const _outer in response[0]) {
for (const _inner in _outer) {
for (const key in _inner) {
headers.push(`${_outer} ${key}`)
}
}
}
But that only gives me: ["input 0", "input 0", "input 0", "input 0", "input 0", "output 0' …] for the headers. For some reason I cannot access the inner keys such as value, name, identifierType, status etc
Can someone please suggest where the above is going wrong / how to get what I am after?
Thanks.
Ok - I managed to get an answer on the Postman Forums - thanks.
the solution is:
for (const outerkey in response[0]){
for (const innerkey in response[0][`${outerkey}`][0]){
headers.push(`${outerkey} ${innerkey}`)
}
}
and gave me:
"input value", "input identifierType", "output value", "output identifierType", "output name", …]
UPDATE: The data items extraction was still hardcoded with key names (e.g. elem.input[0].identifierType and so), so I replaced that also to give the following solution:
function parseData(response, host) {
const results = response.map(function(val, index){
temp = [];
for (const outerkey in val){
for (const innerkey in val[`${outerkey}`][0]){
temp.push(val[`${outerkey}`][0][`${innerkey}`]);
}
}
return temp
}
);
const headers = [];
for (const outerkey in response[0]){
for (const innerkey in response[0][`${outerkey}`][0]){
headers.push(`${outerkey} ${innerkey}`)
}
}
return [results, headers]
}

Export JSON data to CSV file for Excel

Given an array of data objects
const data = [{
"id": "CT20",
"type": "a11y-unknown",
"urls": ["https://www.example.com/test/"]
},
{
"id": "BC192",
"type": "a11y-true",
"urls": [
"https://www.example.com/something/",
"https://www.example.com/another-thing/"
]
}
]
I'm trying to convert the objects to a CSV file that can be imported to Excel so that it shows as:
id | type | urls
CT20 | a11y-unknown| https://www.example.com/test/
I'm using the following to get the keys:
const keys = Object.keys(data[0]);
then map over the data like so:
const commaSeparatedString = [keys.join(","),data.map(row => keys.map(key => row[key]).join(",")).join("\n")].join("\n");
However, this returns the following:
'id,type,urls\nCT20,a11y-unknown,https://www.example.com/test/\nBC192,a11y-true,https://www.example.com/something/,https://www.example.com/another-thing/'
When imported to Excel as a CSV file, and delimited with \, it appears like this:
How can I correctly map the objects so that they are delimited and line break after each set of urls?
const data = [{
"id": "CT20",
"type": "a11y-unknown",
"urls": ["https://www.example.com/test/"]
},
{
"id": "BC192",
"type": "a11y-true",
"urls": [
"https://www.example.com/something/",
"https://www.example.com/another-thing/"
]
}
]
const keys = Object.keys(data[0]);
const commaSeparatedString = [keys.join(","),data.map(row => keys.map(key => row[key]).join(",")).join("\n")].join("\n");
console.log(commaSeparatedString)
You need to have fixed number of columns. So either JSON.stringify the urls array, or designate columns such as url1, url2, url3...
EDIT: naturally if you don't escape commas by enclosing them in quotes, it will break the CSV. Genrally speaking you should use a library for parsing CSV such as papaparse.
const data = [{
"id": "CT20",
"type": "a11y-unknown",
"urls": ["https://www.example.com/test/"]
},
{
"id": "BC192",
"type": "a11y-true",
"urls": [
"https://www.example.com/something/",
"https://www.example.com/another-thing/"
]
}
]
var keys = Object.keys(data[0]);
var arr = [keys, ...data.map(row => keys.map(key => {
return typeof row[key] === "string" ? row[key] : JSON.stringify(row[key])
}))];
// don't!
// .join(",")).join("\n")].join("\n");
// instead
var csv = Papa.unparse(arr);
console.log(csv)
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>
As a general rule, the csv must be delimited with the same delimiter used when importing it, also for reliability all the fields should be included into quotes, so since in your case the delimiter is \, your attempt can be rewritten as below:
const data = [{
"id": "CT20",
"type": "a11y-unknown",
"urls": ["https://www.example.com/test/"]
},
{
"id": "BC192",
"type": "a11y-true",
"urls": [
"https://www.example.com/something/",
"https://www.example.com/another-thing/"
]
}
]
const keys = Object.keys(data[0]);
const commaSeparatedString = [keys.join("\\"),data.map(row => keys.map(key => `"${[row[key]].flat().join()}"`).join("\\")).join("\n")].join("\n");
console.log(commaSeparatedString)

Parse nested JSON Response Javascript

I know there are several threads on this subject but I've looked through over 30 threads without success.
I have managed to parse a JSON response so it looks like this:
{
"1": {
"id": "1",
"name": "Fruit",
.
.
.
"entities": {
"1": {
"id": "1",
"name": "blue bird",
.
.
.
"status": "1"
},
"2": {
using this code
let json = JSON.parse(body);
console.log(json);
Now I want to access the "id", "name" etc. AND the "id" and "name" for the "entities" tag.
So far I have tried:
console.log(json[0]);
console.log(json.id);
which both returns undefined
I have also tried
console.log(json[0].id);
which gives an error
Any ideas?
In this instance, your first key is 1, so you can access it with json[1].
const json = {
"1": {
"id": "1",
"name": "Fruit"
},
"2": {
"id": "2",
"name": "Veggies"
}
};
console.log(json[1]);
In this json, you can reach the id by
json.1.id
But I think that first of all your json is not correctly written, you should have something like
{
"elements": [
{ "id" : 1, "name" : "fruit" },
{ "id" : 2, "name" : "vegetable" }
]
}
like that, json.elements is a collection/array, and you can loop, count, or any other things you will not be able to do because your json looks like a super heavy list of different properties ( he doesn't know that json.1 and json.2 are the same type of objects.
const jsonData = JSON.parse(body);
for (const i in jsonData) {
for (const j in jsonData[i]) {
console.log('${i}: ${jsonData[i][j]}');
}
}

How to convert JSON string having multiple rows to single row using javascript function

I have an output of REST API in following JSON format:
I need to convert the format to flat format so it can be passed as input to another API call.
{
"result": {
"data": [
{
"data": 2.824315071105957,
"dateTime": "2019-09-10T11:32:05.220Z",
"device": { "id": "b3" },
"diagnostic": { "id": "DiagnosticAccelerationForwardBrakingId" },
"controller": "ControllerNoneId",
"version": "00000000000363b0",
"id": "a5UyPzhknSC-N2wtLBph3BA"
},
{
"data": 0,
"dateTime": "2019-09-10T11:32:05.220Z",
"device": { "id": "b3" },
"diagnostic": { "id": "DiagnosticAccelerationSideToSideId" },
"controller": "ControllerNoneId",
"version": "00000000000363b1",
"id": "a5UyPzhknSC-N2wtLBph3BQ"
},
// ... 1000's of rows like this
]
}
}
I need to convert it in below format using a java-script
Desired format:
{"result":{ "data":[{"id":"b3","dateTime":"2019-09- 10T11:32:05.220Z","DiagnosticAccelerationSideToSideId":0,"DiagnosticAccelerationForwardBrakingId ":2.824315071105957},...
The rows needs to be merged with primary key as combination of ID and dateTime attributes. Please note the diagnostic id value becomes key for the required format and data value is the value of the key.
Is there any way to convert this JSON to above flat format.
Need to convert JSON having many rows for single data entry to single row format. Need one java-script function that can accept a string of rows format and convert or merge it and return the string in desired format
function String mergeRows(String flatDataJSONString) {
...
}
If the items are ordered (meaning i and i+1 are merged) than iterate with jumps of i += 2;
If its not ordered or the amount of items to be merged can be > 2 you use an object with unique key composed of the id and date, and override its data whenever a record match this key:
function merger (jsonStr) {
// convert str to obj
const jsonObj = JSON.parse(jsonStr);
const dataObj = {};
for (let i = 0; i < jsonObj.result.length; i++) {
const item = jsonObj.result[i];
// use unique key to merge by
const itemUniqueKey = item.device.id + item.dateTime;
// take last value or create empty object if not exists
const existingItem = dataObj[itemUniqueKey] || {};
// add some logic to merge item with existingItem as you need
...
// set the result back to dataObj to be used on next merges
dataObj[itemUniqueKey] = [merge result of item and existing item];
}
// take dataObj values, you don't need the keys any more
const dataArr = Object.values(dataObj);
const finalResult = {
result: {
data: dataArr
}
}
// convert back to json
return JSON.stringify(finalResult);
}
As stated in the comment you want first to have a clean json definition in order to stringify it. Please get to the following definition of your JSON first:
const json = {
"result": [
{
"data": 2.824315071105957,
"dateTime": "2019-09-10T11:32:05.220Z",
"device": { "id": "b3" },
"diagnostic": { "id": "DiagnosticAccelerationForwardBrakingId" },
"controller": "ControllerNoneId",
"version": "00000000000363b0",
"id": "a5UyPzhknSC-N2wtLBph3BA"
},
{
"data": 0,
"dateTime": "2019-09-10T11:32:05.220Z",
"device": { "id": "b3" },
"diagnostic": { "id": "DiagnosticAccelerationSideToSideId" },
"controller": "ControllerNoneId",
"version": "00000000000363b1",
"id": "a5UyPzhknSC-N2wtLBph3BQ"
}]
};
and then you will be able to perform like hereafter :
JSON.stringify(json)
Hope this helps !

getting a specific value from JSON array with multiple arrays inside in javascript

I'm asking here as I can see this website the most one can help in this
I have an output value in JASON format as the following:
{
"total": 16,
"members": [{
"id": 4,
"name": "Blade11",
"descriptors": {
"os": "Windows 2012 / WS2012 R2"
},
"FCPaths": [{
"wwn": "50060B0000C27208",
"hostSpeed": 0
}, {
"wwn": "50060B0000C2720A",
"hostSpeed": 0
}],
"iSCSIPaths": [],
"persona": 11,
"links": [{
"href": "https://3par:8080/api/v1/hostpersonas?query=\"wsapiAssignedId EQ 11\"",
"rel": "personaInfo"
}],
"initiatorChapEnabled": false,
"targetChapEnabled": false
}, {
"id": 6,
"name": "Blade4",
"descriptors": {
"os": "VMware (ESXi)"
},
"FCPaths": [{
"wwn": "50060B0000C27216",
"hostSpeed": 0
}, {
"wwn": "50060B0000C27214",
"hostSpeed": 0
}],
"iSCSIPaths": [],
"persona": 8,
"links": [{
"href": "https://3par:8080/api/v1/hostpersonas?query=\"wsapiAssignedId EQ 8\"",
"rel": "personaInfo"
}],
"initiatorChapEnabled": false,
"targetChapEnabled": false
}
what I want is, to parse this output for retrieving an output parameter with the name object only in a list or array of string
for example Names = Blade11, Blade4,....
if you can see in the Json output we have all the names under "members", then each one is another array of values, I want to retrieve only names
thanks
If this JSON is string first you have to parse it
var json = JSON.parse('here is your JSON string');
Than you can access to it properties like you work with object
var names = json.members.map(function(member) {
return member.name;
});
Since you already have JSON format, you can use an array method on the member key of your JSON object to iterate through each array item.
var names = [];
object_name.members.forEach((arrItem) => {
names.push(arrItem.name);
}
or
namesArray = object_name.members.map((arrItem) => {
return arrItem.name;
}
You could use Array#map for iterating all elements of the array and return only the name property.
If you have a JSON string, you need to parse it in advance for getting an object, like
object = JSON.parse(jsonString);
var jsonString = '{"total":16,"members":[{"id":4,"name":"Blade11","descriptors":{"os":"Windows 2012 / WS2012 R2"},"FCPaths":[{"wwn":"50060B0000C27208","hostSpeed":0},{"wwn":"50060B0000C2720A","hostSpeed":0}],"iSCSIPaths":[],"persona":11,"links":[{"href":"https://3par:8080/api/v1/hostpersonas?query=\\"wsapiAssignedId EQ 11\\"","rel":"personaInfo"}],"initiatorChapEnabled":false,"targetChapEnabled":false},{"id":6,"name":"Blade4","descriptors":{"os":"VMware (ESXi)"},"FCPaths":[{"wwn":"50060B0000C27216","hostSpeed":0},{"wwn":"50060B0000C27214","hostSpeed":0}],"iSCSIPaths":[],"persona":8,"links":[{"href":"https://3par:8080/api/v1/hostpersonas?query=\\"wsapiAssignedId EQ 8\\"","rel":"personaInfo"}],"initiatorChapEnabled":false,"targetChapEnabled":false}]}',
object = JSON.parse(jsonString),
array = object.members.map(function (a) { return a.name; });
console.log(array);

Categories

Resources