I want to convert JSON responses to CSV format. I was able to figure out how to properly generate the headers in a way where parents of a key are appended together to generate a proper header. The problem I have is structuring the data that corresponds to each row. For example lets say I have these columns called id
, tags
, and friends_id
. Taking the case for id = 1, tags = [car, plane] friends_id = [0,1,2]
. It should kind of look like this in a csv table format.
+-------+-------+------------+
| id | tags | friends_id |
+-------+-------+------------+
| 1 | car | 0 |
+-------+-------+------------+
| empty | plane | 1 |
+-------+-------+------------+
| empty | empty | 2 |
+-------+-------+------------+
| 2 | ... | ... |
+-------+-------+------------+
Here's some test data that I'm working on.
{
"_id": "5cfe7d3c6deeeef08ce0444b",
"name": "Debra Milligain",
"phone": "+1 (906) 432-2182",
"address": "676 Merit Court, Steinhatchee, Oregon, 5491",
"tags": [
"consequat",
"reprehenderit",
"amet"
],
"Work": {
"skills": [{
"id": 0,
"name": "Programming"
},
{
"id": 1,
"name": "Business"
}
]
},
"friends": [{
"id": 0,
"name": "Stafford Hernandez"
},
{
"id": 1,
"name": "Colleen Christensen"
},
{
"id": 2,
"name": "Barker Keith"
}
],
"greeting": [],
"favoriteFruit": "banana"
}
The following code (Which is a solution to an earlier problem I had, found here is what I use to recursively generate headers into a map or hash table and append their corresponding values.
var arrayOfHeaders = {};
var headerDirectory = "";
var rootLevel = true;
var temp = ""
var firstWalkthrough = true;
function traverseJSON(obj){
for (var o in obj) {
if (typeof obj[o] == "object") {
//console.log("Before traversal ", o)
//console.log("Traversing the object: ", obj[o])
if(!isNaN(o)){
//console.log("Current position is a number ", o)
}else{
console.log("Adding to directory... " , o)
headerDirectory += (headerDirectory == "") ? o : "_" + o;
}
rootLevel = false;
if (firstWalkthrough){
firstWalkthrough = false;
//if (o == 0)
rootLevel = true;
}
traverseJSON(obj[o]);
rootLevel = true;
temp = headerDirectory;
headerDirectory = "";
} else {
if (rootLevel) {
if(isNaN(o)){
headerDirectory = "";
//console.log("Has value and is root ", o, "and temp ", temp)
arrayOfHeaders[o] += ",\"" + obj[o] + "\"";
}else{
arrayOfHeaders[headerDirectory+"_"+o] += ",\"" + obj[o] + "\"";
}
}
else {
//console.log("Has value and is not root ", o)
//console.log("Current Header Directory " + headerDirectory)
//console.log("Saved temp : ", temp)
if(isNaN(o)){
if(headerDirectory == "") headerDirectory = temp;
//arrayOfHeaders.push(headerDirectory + "_" + o)
arrayOfHeaders[headerDirectory + "_" + o] += ",\"" + obj[o] + "\"";
}
}
}
}
// console.log("Array of Headers : ", arrayOfHeaders)
}
This is the actual response from arrayofHeaders:
{ _id: 'undefined,"5cfe7d3c6deeeef08ce0444b"',
name: 'undefined,"Debra Milligain"',
phone: 'undefined,"+1 (906) 432-2182"',
address: 'undefined,"676 Merit Court, Steinhatchee, Oregon, 5491"',
tags_0: 'undefined,"consequat"',
tags_1: 'undefined,"reprehenderit"',
tags_2: 'undefined,"amet"',
'Work_skills_id-skill': 'undefined,"0","Business"',
'Work_skills_name-skill': 'undefined,"Programming"',
'friends_id-friends': 'undefined,"0","1","2"',
'friends_name-friends':
'undefined,"Stafford Hernandez","Colleen Christensen","Barker Keith"',
favoriteFruit: 'undefined,"banana"' }
I want to structure the data in such a way that it would be easy to loop through and produce a csv like this. The issue is that I'm not sure how to make the leap from whats above to whats below.
+--------------------------+-----------------+-------------------+---------------------------------------------+---------------+------------------------+--------------------------+---------------------+-----------------------+---------------+
| _id | name | phone | address | tags | Work__skills__id-skill | Work__skills__name-skill | friends__id-friends | friends__name-friends | favoriteFruit |
+--------------------------+-----------------+-------------------+---------------------------------------------+---------------+------------------------+--------------------------+---------------------+-----------------------+---------------+
| 5cfe7d3c6deeeef08ce0444b | Debra Milligain | +1 (906) 432-2182 | 676 Merit Court, Steinhatchee, Oregon, 5491 | consequat | 0 | Programming | 0 | Stafford Hernandez | banana |
+--------------------------+-----------------+-------------------+---------------------------------------------+---------------+------------------------+--------------------------+---------------------+-----------------------+---------------+
| | | | | reprehenderit | Business | | 1 | Colleen Christensen | |
+--------------------------+-----------------+-------------------+---------------------------------------------+---------------+------------------------+--------------------------+---------------------+-----------------------+---------------+
| | | | | amet | | | 2 | Barker Keith | |
+--------------------------+-----------------+-------------------+---------------------------------------------+---------------+------------------------+--------------------------+---------------------+-----------------------+---------------+
EDIT: El Tom - possible fix of your code
var arrayOfHeaders = {};
var headerDirectory = "";
var rootLevel = true;
var temp = ""
var firstWalkthrough = true;
traverseJSON(
JSON.parse('{"_id": "5cfe7d3c6deeeef08ce0444b","name": "Debra Milligain","phone": "+1 (906) 432-2182","address": "676 Merit Court, Steinhatchee, Oregon, 5491","tags": ["consequat","reprehenderit","amet"],"Work": {"skills": [{"id": 0,"name": "Programming"},{"id": 1,"name": "Business"}]},"friends": [{"id": 0,"name": "Stafford Hernandez"},{"id": 1,"name": "Colleen Christensen"},{"id": 2,"name": "Barker Keith"}],"greeting": [],"favoriteFruit": "banana"}')
)
function traverseJSON(obj) {
for (var o in obj) {
if (typeof obj[o] == "object") {
//console.log("Before traversal ", o)
//console.log("Traversing the object: ", obj[o])
if (!isNaN(o)) {
//console.log("Current position is a number ", o)
} else {
console.log("Adding to directory... ", o)
headerDirectory += (headerDirectory == "") ? o : "_" + o;
}
rootLevel = false;
if (firstWalkthrough) {
firstWalkthrough = false;
//if (o == 0)
rootLevel = true;
}
traverseJSON(obj[o]);
rootLevel = true;
temp = headerDirectory;
headerDirectory = "";
} else {
if (rootLevel) {
if (isNaN(o)) {
headerDirectory = "";
//console.log("Has value and is root ", o, "and temp ", temp)
if (arrayOfHeaders[o] !== undefined) {
arrayOfHeaders[o].push(obj[o]);
} else {
arrayOfHeaders[o] = [obj[o]];
}
} else {
if (arrayOfHeaders[headerDirectory + "_" + o] !== undefined) {
arrayOfHeaders[headerDirectory + "_" + o].push(obj[o]);
} else {
arrayOfHeaders[headerDirectory + "_" + o] = [obj[o]];
}
}
}
else {
//console.log("Has value and is not root ", o)
//console.log("Current Header Directory " + headerDirectory)
//console.log("Saved temp : ", temp)
if (isNaN(o)) {
if (headerDirectory == "") headerDirectory = temp;
//arrayOfHeaders.push(headerDirectory + "_" + o)
if (arrayOfHeaders[headerDirectory + "_" + o] !== undefined) {
arrayOfHeaders[headerDirectory + "_" + o].push(obj[o]);
} else {
arrayOfHeaders[headerDirectory + "_" + o] = [obj[o]];
}
}
}
}
}
}
var res = JSON.stringify(arrayOfHeaders).replace(/,"/g, ',\n"')
console.log("Easier Arrays in Array printed by JSON.stringify:\n", res)
res = {
"_id": ["5cfe7d3c6deeeef08ce0444b"],
"name": ["Debra Milligain"],
"phone": ["+1 (906) 432-2182"],
"address": ["676 Merit Court, Steinhatchee, Oregon, 5491"],
"tags_0": ["consequat"],
"tags_1": ["reprehenderit"],
"tags_2": ["amet"],
"Work_skills_id": [0, 1],
"Work_skills_name": ["Programming",
"Business"],
"friends_id": [0, 1, 2],
"friends_name": ["Stafford Hernandez",
"Colleen Christensen",
"Barker Keith"],
"favoriteFruit": ["banana"]
};
var yourResult = "";
for(var i in arrayOfHeaders) {
if(arrayOfHeaders[i].length > 1) {
arrayOfHeaders[i] = '"' + arrayOfHeaders[i].join('","') + '"';
} else {
arrayOfHeaders[i] = '"' + arrayOfHeaders[i] + '"';
}
yourResult += i + ':' + arrayOfHeaders[i] + '\n';
}
console.log("\nProbably result you wanted to collect but invalid JSON format:\n", yourResult);
But if you compare them with my answer, printed structure is the same, but not as your manualy generated table (probably some errors).