JSON到CSV转换(JavaScript):如何正确设置CSV转换格式 [英] JSON To CSV conversion (JavaScript) : How to properly format CSV conversion

查看:97
本文介绍了JSON到CSV转换(JavaScript):如何正确设置CSV转换格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将JSON响应转换为CSV格式。我能够弄清楚如何正确地生成标头,其中将键的父级附加在一起以生成合适的标头。我遇到的问题是构造与每一行相对应的数据。例如,假设我有以下列,分别为 id 标签 friends_id 。以 id = 1的情况为例,标签= [汽车,飞机] friends_id = [0,1,2]

  + ------- + ---- --- + ------------ + 
| id |标签| friends_id |
+ ------- + ------- + ------------ +
| 1 |汽车| 0 |
+ ------- + ------- + ------------ +
|空的飞机1 |
+ ------- + ------- + ------------ +
|空的空的2 |
+ ------- + ------- + ------------ +
| 2 | ... | ... |
+ ------- + ------- + ------------ +

以下是我正在处理的一些测试数据。

  {
_id: 5cfe7d3c6deeeef08ce0444b,
名称: Debra Milligain,
电话: + 1(906)432-2182,
地址 :: 676 Merit Court,Steinhatchee,Oregon,5491,
tags:[
consequat,
reprehenderit,
amet
] ,
工作:{
技能:[{
id:0,
名称:编程
},
{
id:1,
name: Business
}
]
},
friends:[{
id:0,
name: Stafford Hernandez
},
{
id:1,
name: Colleen Christensen
},
{
id:2,
name: Barker Kei th
}
],
greeting:[],
favoriteFruit: banana
}

以下代码(这是我以前遇到的一个问题的解决方案,找到了此处是我用来递归地将头生成到地图或哈希表中并追加的内容

  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( 遍历之前,o)
//console.log(遍历对象:,obj [o])
if(!isNaN(o)){
//控制台。 log(当前位置是一个数字,o)
} else {
console.log(添加到目录...,o)
headerDirectory + =(headerDirectory == )? o: _ + o;
}
rootLevel = false;
if(firstWalkthrough){
firstWalkthrough = false;
//如果(o == 0)
rootLevel = true;
}

traverseJSON(obj [o]);
rootLevel = true;
temp = headerDirectory;
headerDirectory =;
} else {
if(rootLevel){
if(isNaN(o)){
headerDirectory =;
//console.log(具有值并且是根,o,和temp,temp)
arrayOfHeaders [o] + =,\ + obj [o] + \;
} else {
arrayOfHeaders [headerDirectory + _ + o] + =,\ + obj [o] + \;
}

}
else {
//console.log(具有值且不是root,o)
//console.log (当前标头目录 + headerDirectory)
//console.log(保存的温度:,温度)
if(isNaN(o)){
if(headerDirectory == )headerDirectory = temp;
//arrayOfHeaders.push(headerDirectory + _ + o)
arrayOfHeaders [headerDirectory + _ + o] + =,\ + obj [o] + \ ;
}
}
}
}
// console.log( Header数组:,arrayOfHeaders)
}

这是来自arrayofHeaders的实际响应:

  {_id:'undefined, 5cfe7d3c6deeeef08ce0444b',
名称:'undefined, Debra Milligain',
电话:'undefined, + 1(906)432-2182 ',
地址:'undefined, 676 Merit Court,Steinhatchee,Oregon,5491,
标签_0:'undefined, consequat',
标签_1:'undefined, reprehenderit ',
标签_2:'undefined, amet',
'Work_skills_id-skill':'undefined, 0, Business',
'Work_skills_name-skill':'undefined ,编程',
'friends_id-friends':'未定义', 0, 1, 2',
'friends_name-friends':
'未定义', Stafford Hernandez, Colleen Christensen, Barker Keith,
最喜欢的水果:'undefined, banana'}

我想以这种方式构造数据t帽子很容易循环通过并产生这样的csv。问题是我不确定如何实现从上到下的飞跃。

  + ---- ---------------------- + ----------------- + --------- ---------- + --------------------------------------- ------ + --------------- + ------------------------ +- ------------------------ + --------------------- + --- -------------------- + --------------- + 
| _id |名称|电话|地址|标签|工作__技能__id-技能|工作__技能__名称技能|朋友__id-朋友| friends__name-friends |最喜欢的水果|
+ -------------------------- + ----------------- + ------------------- + ------------------------------ --------------- + --------------- + ------------------ ------ + -------------------------- + ---------------- ----- + ----------------------- + --------------- +
| 5cfe7d3c6deeeef08ce0444b | Debra Milligain | +1(906)432-2182 |俄勒冈州Steinhatchee 676优异法院| 5491 |结果| 0 |程式设计0 |斯塔福德·埃尔南德斯|香蕉|
+ -------------------------- + ----------------- + ------------------- + ------------------------------ --------------- + --------------- + ------------------ ------ + -------------------------- + ---------------- ----- + ----------------------- + --------------- +
| | | | | reprehenderit |商业| | 1 |科琳·克里斯滕森| |
+ -------------------------- + ----------------- + ------------------- + ------------------------------ --------------- + --------------- + ------------------ ------ + -------------------------- + ---------------- ----- + ----------------------- + --------------- +
| | | | | amet | | | 2 |巴克·基思| |
+ -------------------------- + ----------------- + ------------------- + ------------------------------ --------------- + --------------- + ------------------ ------ + -------------------------- + ---------------- ----- + ----------------------- + --------------- +

编辑: El Tom-代码的可能解决方法

< pre class = snippet-code-js lang-js prettyprint-override> 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 ,俄勒冈州5491,标签:[结果, reprehenderit, amet],工作:{技能:[{ id:0,名称:编程}, { id:1,名称: Business}]}},朋友:[{ id:0,名称: Stafford Hernandez },{ id:1,名称: Colleen Christensen},{ id:2,名称: Barker Keith}],问候:[], favoriteFruit: banana}'))函数traverseJSON(obj){for(obj中的var o){if(typeof obj [o] == object){//console.log(遍历之前,o)//控制台.log(遍历对象:,obj [o])if(!isNaN(o)){//console.log(当前位置是数字,o)} else {console.log(添加到目录...,o)headerDirectory + =(headerDirectory ==)? o: _ + o; } rootLevel = false;如果(firstWalkthrough){firstWalkthrough = false; //如果(o == 0)rootLevel = true; } traverseJSON(obj [o]); rootLevel = true; temp = headerDirectory; headerDirectory =; } else {if(rootLevel){if(isNaN(o)){headerDirectory =; //console.log(具有值并且是根,o,和temp,temp)if(arrayOfHeaders [o]!==未定义){arrayOfHeaders [o] .push(obj [o]); } else {arrayOfHeaders [o] = [obj [o]]; }} else {if(arrayOfHeaders [headerDirectory + _ + o]!==未定义){arrayOfHeaders [headerDirectory + _ + o] .push(obj [o]); } else {arrayOfHeaders [headerDirectory + _ + o] = [obj [o]]; }}} else {//console.log(具有值并且不是根目录,o)//console.log(当前头目录 + headerDirectory)//console.log(\"Saved temp:,temp) if(isNaN(o)){if(headerDirectory ==)headerDirectory = temp; //arrayOfHeaders.push(headerDirectory + _ + o)if(arrayOfHeaders [headerDirectory + _ + o]!==未定义){arrayOfHeaders [headerDirectory + _ + o] .push(obj [o]) ; } else {arrayOfHeaders [headerDirectory + _ + o] = [obj [o]]; var res = JSON.stringify(arrayOfHeaders).replace(/, / g,',\n')console.log( JSON轻松打印数组中的数组。stringify:\n ,res)res = { _id:[ 5cfe7d3c6deeeef08ce0444b],名称:[ Debra Milligain],电话:[ +1(906)432-2182],地址:[ 676 Merit Court,Steinhatchee,俄勒冈州,5491], tags_0:[ consequat], tags_1:[ reprehenderit], tags_2:[ amet], Work_skills_id:[0, 1], Work_skills_name:[编程,业务], 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( \n可能要收集的结果是无效的JSON格式:\n,yourResult);



但是,如果将它们与我的答案进行比较,则打印结构是相同的,而不是您手动生成的表(可能有一些错误)。

解决方案

是它了(必须运行代码段以查看结果)作为HTML表演示-不知道如何将其直接放在此处)?



 功能readDown(headName,arr,outRows){var under = [headName]; while(arr.toString()。indexOf( [object)== 0 || Array.isArray(arr)){var hasArray = false; for(var i in arr){if(arr [i] .toString()。indexOf( [object)== 0 || Array.isArray(arr [i]))hasArray = true; } if(hasArray){for(ar中的var i)if(arr [i] .toString()。indexOf( [object)== 0 || Array.isArray(arr [i])){if(isNaN (i))在[0] + ='_'+ i下; readDown(under [0],arr [i],outRows);如果(arr.length === undefined)返回; //空关联(技能)delete arr [i ++]; var next = false; //是否有以下要分组的数组? while(i&& arr [i-1] === undefined& i< arr.length&&(arr [i] .toString()。indexOf( [object)== 0 || Array.isArray(arr [i]))){//对整个最低数组进行分组next = true; var idx = outRows.length-1如果(!Array.isArray(outRows [idx] [1])){outRows [idx] [1] = [outRows [idx] [1],arr [i ++]]; } else outRows [idx] [1] .push(arr [i ++]);删除arr [i-1]; } if(next&& i == arr.length){arr.length = 0; //充满未定义成员的数组,固定长度,以防返回null; //然后返回-我们在这里完成了}}}其他{//如果(hasArray& isNaN(i))低于[0] + =‘_’+ i; under.push(arr [i]);打破; }}} else {if(arr.length === undefined){// Work_skills [0],friends [0] under.push(arr); outRows.push(under); } else {//标签,问候if(!arr.length)返回; //不要在.push(arr [i]);下为(var i in arr)保留空的问候。 outRows.push(under);返回null; // //所有数组都返回此处} //无法访问的下一个}}函数JSON2CSV(arr,inRows,outRows){var row = []; var hasArray = false; for(var a in arr){试试{if(arr [a] == null){//将null更改为字符串arr [a] = null; }如果(Array.isArray(arr [a])|| arr [a] .toString()。indexOf( [object)== 0){readDown(a,arr [a],outRows);继续; } else {if(isNaN(a)){outRows.push([a,arr [a]]); } else {outRows.push(['#’,arr [a]]); }}} catch(e){return e; }}} function convert(json){var JSONtxt;尝试{JSONtxt = JSON.parse(json); } catch(e){console.log(e);返回; } var columnsArray = []; JSON2CSV(JSONtxt,[],columnsArray); var maxDepth = 1; //如果(Array.isArray(columnsArray [i] [1])&& maxDepth< columnsArray [i] [1] .length)maxDepth = columnsArray [i ] [1] .length; maxDepth ++; var csv = []; for(var c in columnsArray){if(Array.isArray(columnsArray [c] [1]))){var r = 0; for(在ColumnArray [c] [1] [r]中的var nd){csv.push([columnsArray [c] [0] +'_'+ nd]);; //顶部标头var col = csv.length-1; for(; r< columnsArray [c] [1] .length; r ++){csv [col] .push(columnsArray [c] [1] [r] [nd]); //键的值删除columnArray [c] [1] [r] [nd]; } r = 0; }} else {csv.push(columnsArray [c]); } while(csv [c] .length&maxDepth)csv [c] .push(null); } var csvTxt =; //制表符分隔的值(复制/粘贴2 XL吗?)var htmlTab =< TABLE border = \ 1\ width = \ 1500\>; for(var r = 0; r< maxDepth; r ++){htmlTab + =< TR>; for(csv中的var c){htmlTab + = r == 0?< TH:< TD; //如果(c!= 0)csvTxt + =‘\t’,也要注意第一个标题行;如果(csv [c] [r]!= null){csvTxt + = csv [c] [r]; htmlTab + => + csv [c] [r]; } else htmlTab + = class = empty> htmlTab + =< / TD>; } csvTxt + =’\r\n’; htmlTab + = r == 0?< / TH>:< / TR> ;; } htmlTab + =< / TABLE>; return htmlTab;} var json ='{ _id: 5cfe7d3c6deeeef08ce0444b, name: Debra Milligain, phone: +1(906)432-2182, address: 676 Merit Court, Steinhatchee,俄勒冈州,5491,标签:[结果, reprehenderit, amet],工作:{技能:[{ id:0,名称:编程} ,{ id:1,名称:业务}]}},朋友:[{ id:0,名称: Stafford Hernandez},{ id:1,名称: Colleen Christensen},{ id:2, name: Barker Keith}}, greeting:[], favoriteFruit: banana}'';  

  table {border-spacing:0px; / *小技巧2使圆桌简单或* /} th {text-align:left; / *居中看起来很难看* /} td.empty {background-color:lightgray; / *标记空单元格* /}  

 < body onload = document.body.innerHTML = convert(json)>< / body>  



未对代码段进行整洁修改的原始代码:

  function readDown(headName,arr,outRows){ 
var under = [headName];
while(arr.toString()。indexOf( [object)== 0
|| Array.isArray(arr)){
var hasArray = false;
for(var in in arr){
if(arr [i] .toString()。indexOf( [object)== 0
|| Array.isArray(arr [i ]))hasArray = true;
}
if(hasArray){
for(var i in arr)
if(arr [i] .toString()。indexOf( [object)== 0
|| Array.isArray(arr [i])){
if(isNaN(i))under [0] + ='_'+ i;
readDown(under [0],arr [i],outRows);
if(arr.length ===未定义)
返回; //空关联(技能)
delete arr [i ++];
var next = false; //是否有以下要分组的数组?
while(i&& arr [i-1] ===未定义&& i< arr.length&&&(amp; arr [i] .toString()。indexOf( [ )== 0
|| Array.isArray(arr [i]))){//将整个最低数组
分组= true;
var idx = outRows.length-1
if(!Array.isArray(outRows [idx] [1])){
outRows [idx] [1] = [outRows [idx] [1],arr [i ++]];
} else outRows [idx] [1] .push(arr [i ++]);
delete arr [i-1];
}
if(next&& i == arr.length){
arr.length = 0; //充满未定义成员的数组,如果
返回null,则固定长度; //然后返回-我们在这里完成了
}
} else {//如果(hasArray&& isNaN(i))低于[0],== '_'+我;
under.push(arr [i]);
休息时间;
}
} else {
if(arr.length === undefined){//工作技能[0],朋友[0]
under.push(arr);
outRows.push(under);
} else {//标签,问候
if(!arr.length)返回; //不要为.push(arr [i]);下的(var i in arr)保留空的问候

outRows.push(under);
}
返回null; //所有数组都返回此处
}
//无法访问的下一个
}
}
函数JSON2CSV(arr,inRows,outRows){
var row = [];
var hasArray = false;
for(var a in arr){
try {
if(arr [a] == null){//将null更改为字符串
arr [a] = null ;
}
if(Array.isArray(arr [a])|| arr [a] .toString()。indexOf( [object)== 0){
readDown(a ,arr [a],outRows);
继续;
} else {
if(isNaN(a)){
outRows.push([a,arr [a]]);
} else {
outRows.push([’#’,arr [a]]);
}
}
}抓住(e){
return e;
}
}
}
function convert(json){
var JSONtxt;
try {
JSONtxt = JSON.parse(json);
} catch(e){
console.log(e);
的回报;
}
var columnsArray = [];
JSON2CSV(JSONtxt,[],columnsArray);
var maxDepth = 1; //找到(Array.isArray(columnsArray [i] [1])$ ​​b $ b&& maxDepth< columnsArray [i]的最长的最低数组大小
] [1] .length)
maxDepth = columnsArray [i] [1] .length;
maxDepth ++;
var csv = [];
for(vars in columnsArray){
if(Array.isArray(columnsArray [c] [1])){{b $ b var r = 0;
for(vars in columnsArray [c] [1] [r]){
csv.push([columnsArray [c] [0] + __ + nd]);; //顶部标头
var col = csv.length-1;
for(; r< columnsArray [c] [1] .length; r ++){
csv [col] .push(columnsArray [c] [1] [r] [nd]); //键的值
delete columnsArray [c] [1] [r] [nd];
}
r = 0;
}

} else {
csv.push(columnsArray [c]);
}
而(csv [c] .length< maxDepth)csv [c] .push(null);
}
var csvTxt =; //制表符分隔的值(复制/粘贴2 XL吗?)
var htmlTab =< TABLE border = \ 1\>;
for(var r = 0; r< maxDepth; r ++){
htmlTab + =< TR>;
for(csv中的var c){
htmlTab + =< TD>;
if(c!= 0)csvTxt + =‘\t’;
if(csv [c] [r]!= null){
csvTxt + = csv [c] [r];
htmlTab + = csv [c] [r];
}
htmlTab + =< / TD>;
}
csvTxt + =’\r\n’;
htmlTab + =< / TR>;
}
htmlTab + =< / TABLE>;
console.log(csvTxt);
console.log(htmlTab);
}
var json ='{ _id: 5cfe7d3c6deeeef08ce0444b, name: Debra Milligain, phone: +1(906)432-2182, address: 676 Merit Court,Steinhatchee,Oregon,5491,标签:[结果, reprehenderit, amet],工作:{技能:[{ id:0,名称 :正在编程},{ id:1,名称:业务}]}},朋友:[{ id:0,名称:斯塔福德·埃尔南德斯},{ id :1, name: Colleen Christensen},{ id:2, name: Barker Keith}], greeting:[], favoriteFruit: banana}';;
convert(json);

甚至是我原来的 JSONoperations.hta CSV导出看起来并不糟糕,但是有点旋转并且包括无用的1级编号,无论如何,如果我从这里开始;-)



  table {border-spacing:0px; } th {text-align:left; } td.empty {background-color:lightgray;}  

  < TABLE border = 1 width = 900>< TR>< TD>标签< / TD>< TD> 0< / TD>< TD> 1< / TD>< TD> 2< / TD> / TR< TR>< TD class = empty< / TD< TD" / TD< TD> preprehenderit< / TD< TD> ; amet / TD< TR> TR< TD> Work< / TD< TD>技能// TD< TD>#< / TD< TD> id< / TD< TD>名称< / TD< / TR>< TR>< TD class = empty< / TD>< TD class = empty< / TD> < TD> 1 / TD< TD> 0< / TD>< TD> / TD< / TR>< TR>< TD class = empty< / TD> ;< TD class = empty< / TD>< TD> 2< TD< TD> 1< / TD>< TD>< TD>< / TR>< TR< TD> /< TD>#< / TD< TD> id< / TD< TD>名称< / TD>< ; / TR>< TR>< TD class = empty< / TD>< TD> 1< / TD> TD< 0> / TD< TD>斯塔福德·赫尔南德斯< / TD> ;< / TR>< TD class = empty< / TD>< TD> 2< TD< TD>< TD< 1> / TD< TD< Colleen Christensen< / TD< / TR>< TD class = empty< / TD< TD< 3> / TD< TD> 2< / TD< TD>巴克Keith< TD> / TR> TR< TD> _id< TD< TD>名称< / TD< TD>电话< / TD>< TD>地址< / TD> < TD>最喜欢的水果/ TD< / TR> TR< TD> 5cfe7d3c6deeeef08ce0444b< TD> TD> Debra Milligain< TD>< 182> -1(906) / TD< TD> 676 Merit Court,俄勒冈州Steinhatchee,5491< / TD< TD"香蕉< / TD< / TR< / TABLE>  


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).

解决方案

Is that it (have to run the snippet to see results as HTML table demo - do not know how to put it here directly) ?

function readDown(headName, arr, outRows) {
    var under = [headName];
    while (arr.toString().indexOf("[object") == 0
        || Array.isArray(arr)) {
        var hasArray = false;
        for (var i in arr) {
            if (arr[i].toString().indexOf("[object") == 0
                || Array.isArray(arr[i])) hasArray = true;
        }
        if (hasArray) {
            for (var i in arr)
                if (arr[i].toString().indexOf("[object") == 0
                    || Array.isArray(arr[i])) {
                    if (isNaN(i)) under[0] += '_' + i;
                    readDown(under[0], arr[i], outRows);
                    if (arr.length === undefined)
                        return; // empty associative (skills)
                    delete arr[i++];
                    var next = false; // are there following arrays to be groupped ?
                    while (i && arr[i - 1] === undefined && i < arr.length && (arr[i].toString().indexOf("[object") == 0
                        || Array.isArray(arr[i]))) { // group whole lowest array
                        next = true;
                        var idx = outRows.length - 1
                        if (!Array.isArray(outRows[idx][1])) {
                            outRows[idx][1] = [outRows[idx][1], arr[i++]];
                        } else outRows[idx][1].push(arr[i++]);
                        delete arr[i - 1];
                    }
                    if (next && i == arr.length) {
                        arr.length = 0; // array full of undefined members, fix length in case
                        return null; // and return - we are done here
                    }
                } else { // funny never get there now
                    if (hasArray && isNaN(i)) under[0] += '_' + i;
                    under.push(arr[i]);
                    break;
                }
        } else {
            if (arr.length === undefined) { // Work_skills[0], friends[0]
                under.push(arr);
                outRows.push(under);
            } else { // tags, greetings
                if(!arr.length) return; // do not keep empty greetings
                for (var i in arr) under.push(arr[i]);
                outRows.push(under);
            }
            return null; // all arrays return here
        }
        // unreachable next
    }
}
function JSON2CSV(arr, inRows, outRows) {
    var row = [];
    var hasArray = false;
    for (var a in arr) {
        try {
            if (arr[a] == null) { // Change null's to string
                arr[a] = "null";
            }
            if (Array.isArray(arr[a]) || arr[a].toString().indexOf("[object") == 0) {
                readDown(a, arr[a], outRows);
                continue;
            } else {
                if (isNaN(a)) {
                    outRows.push([a, arr[a]]);
                } else {
                    outRows.push(['#', arr[a]]);
                }
            }
        } catch (e) {
            return e;
        }
    }
}
function convert(json) {
    var JSONtxt;
    try {
        JSONtxt = JSON.parse(json);
    } catch (e) {
        console.log(e);
        return;
    }
    var columnsArray = [];
    JSON2CSV(JSONtxt, [], columnsArray);
    var maxDepth = 1; // find longest lowest array size
    for (var i in columnsArray)
        if (Array.isArray(columnsArray[i][1])
            && maxDepth < columnsArray[i][1].length)
            maxDepth = columnsArray[i][1].length;
    maxDepth++;
    var csv = [];
    for (var c in columnsArray) {
        if (Array.isArray(columnsArray[c][1])) {
            var r = 0;
            for (var nd in columnsArray[c][1][r]) {
                csv.push([columnsArray[c][0] + '_' + nd]); // top header
                var col = csv.length - 1;
                for (; r < columnsArray[c][1].length; r++) {
                    csv[col].push(columnsArray[c][1][r][nd]); // key's value
                    delete columnsArray[c][1][r][nd];
                }
                r = 0;
            }

        } else {
            csv.push(columnsArray[c]);
        }
        while (csv[c].length < maxDepth) csv[c].push(null);
    }
    var csvTxt = ""; // tab separated values (copy/paste 2 XL ?)
    var htmlTab = "<TABLE border=\"1\" width=\"1500\">";
    for (var r = 0; r < maxDepth; r++) {
        htmlTab += "<TR>";
        for (var c in csv) {
            htmlTab += r==0?"<TH":"<TD"; // mind 1st header row too
            if (c != 0) csvTxt += '\t';
            if (csv[c][r] != null) {
                csvTxt += csv[c][r];
                htmlTab += ">" + csv[c][r];
            } else htmlTab += " class=empty>"
            htmlTab += "</TD>";
        }
        csvTxt += '\r\n';
        htmlTab += r==0?"</TH>":"</TR>";
    }
    htmlTab += "</TABLE>";
    return htmlTab;
}
var json = '{"_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"}';

table {
  border-spacing: 0px; /* small tricks 2 make rounded table simply or */
}
th {
  text-align:left; /* centered looks ugly */
}
td.empty {
  background-color:lightgray; /* mark null cells */
}

<body onload="document.body.innerHTML=convert(json)"></body>

Original code without tidy modifications for the snippet:

function readDown(headName, arr, outRows) {
    var under = [headName];
    while (arr.toString().indexOf("[object") == 0
        || Array.isArray(arr)) {
        var hasArray = false;
        for (var i in arr) {
            if (arr[i].toString().indexOf("[object") == 0
                || Array.isArray(arr[i])) hasArray = true;
        }
        if (hasArray) {
            for (var i in arr)
                if (arr[i].toString().indexOf("[object") == 0
                    || Array.isArray(arr[i])) {
                    if (isNaN(i)) under[0] += '_' + i;
                    readDown(under[0], arr[i], outRows);
                    if (arr.length === undefined)
                        return; // empty associative (skills)
                    delete arr[i++];
                    var next = false; // are there following arrays to be groupped ?
                    while (i && arr[i - 1] === undefined && i < arr.length && (arr[i].toString().indexOf("[object") == 0
                        || Array.isArray(arr[i]))) { // group whole lowest array
                        next = true;
                        var idx = outRows.length - 1
                        if (!Array.isArray(outRows[idx][1])) {
                            outRows[idx][1] = [outRows[idx][1], arr[i++]];
                        } else outRows[idx][1].push(arr[i++]);
                        delete arr[i - 1];
                    }
                    if (next && i == arr.length) {
                        arr.length = 0; // array full of undefined members, fix length in case
                        return null; // and return - we are done here
                    }
                } else { // funny never get there now
                    if (hasArray && isNaN(i)) under[0] += '_' + i;
                    under.push(arr[i]);
                    break;
                }
        } else {
            if (arr.length === undefined) { // Work_skills[0], friends[0]
                under.push(arr);
                outRows.push(under);
            } else { // tags, greetings
                if(!arr.length) return; // do not keep empty greetings
                for (var i in arr) under.push(arr[i]);
                outRows.push(under);
            }
            return null; // all arrays return here
        }
        // unreachable next
    }
}
function JSON2CSV(arr, inRows, outRows) {
    var row = [];
    var hasArray = false;
    for (var a in arr) {
        try {
            if (arr[a] == null) { // Change null's to string
                arr[a] = "null";
            }
            if (Array.isArray(arr[a]) || arr[a].toString().indexOf("[object") == 0) {
                readDown(a, arr[a], outRows);
                continue;
            } else {
                if (isNaN(a)) {
                    outRows.push([a, arr[a]]);
                } else {
                    outRows.push(['#', arr[a]]);
                }
            }
        } catch (e) {
            return e;
        }
    }
}
function convert(json) {
    var JSONtxt;
    try {
        JSONtxt = JSON.parse(json);
    } catch (e) {
        console.log(e);
        return;
    }
    var columnsArray = [];
    JSON2CSV(JSONtxt, [], columnsArray);
    var maxDepth = 1; // find longest lowest array size
    for (var i in columnsArray)
        if (Array.isArray(columnsArray[i][1])
            && maxDepth < columnsArray[i][1].length)
            maxDepth = columnsArray[i][1].length;
    maxDepth++;
    var csv = [];
    for (var c in columnsArray) {
        if (Array.isArray(columnsArray[c][1])) {
            var r = 0;
            for (var nd in columnsArray[c][1][r]) {
                csv.push([columnsArray[c][0] + '_' + nd]); // top header
                var col = csv.length - 1;
                for (; r < columnsArray[c][1].length; r++) {
                    csv[col].push(columnsArray[c][1][r][nd]); // key's value
                    delete columnsArray[c][1][r][nd];
                }
                r = 0;
            }

        } else {
            csv.push(columnsArray[c]);
        }
        while (csv[c].length < maxDepth) csv[c].push(null);
    }
    var csvTxt = ""; // tab separated values (copy/paste 2 XL ?)
    var htmlTab = "<TABLE border=\"1\">";
    for (var r = 0; r < maxDepth; r++) {
        htmlTab += "<TR>";
        for (var c in csv) {
            htmlTab += "<TD>";
            if (c != 0) csvTxt += '\t';
            if (csv[c][r] != null) {
                csvTxt += csv[c][r];
                htmlTab += csv[c][r];
            }
            htmlTab += "</TD>";
        }
        csvTxt += '\r\n';
        htmlTab += "</TR>";
    }
    htmlTab += "</TABLE>";
    console.log(csvTxt);
    console.log(htmlTab);
}
var json = '{"_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"}';
convert(json);

And even my original JSONoperations.hta CSV export does not look so bad, but a bit rotated and includes useless 1-level numbering, anyway if I would start here ;-)

table { border-spacing: 0px; }
th { text-align:left; }
td.empty { background-color:lightgray;}

<TABLE border="1" width="900"><TR><TD>tags</TD><TD>0</TD><TD>1</TD><TD>2</TD></TR><TR><TD class="empty"></TD><TD>consequat</TD><TD>reprehenderit</TD><TD>amet</TD></TR><TR><TD>Work</TD><TD>skills</TD><TD>#</TD><TD>id</TD><TD>name</TD></TR><TR><TD class="empty"></TD><TD class="empty"></TD><TD>1</TD><TD>0</TD><TD>Programming</TD></TR><TR><TD class="empty"></TD><TD class="empty"></TD><TD>2</TD><TD>1</TD><TD>Business</TD></TR><TR><TD>friends</TD><TD>#</TD><TD>id</TD><TD>name</TD></TR><TR><TD class="empty"></TD><TD>1</TD><TD>0</TD><TD>Stafford Hernandez</TD></TR><TR><TD class="empty"></TD><TD>2</TD><TD>1</TD><TD>Colleen Christensen</TD></TR><TR><TD class="empty"></TD><TD>3</TD><TD>2</TD><TD>Barker Keith</TD></TR><TR><TD>_id</TD><TD>name</TD><TD>phone</TD><TD>address</TD><TD>favoriteFruit</TD></TR><TR><TD>5cfe7d3c6deeeef08ce0444b</TD><TD>Debra Milligain</TD><TD>+1 (906) 432-2182</TD><TD>676 Merit Court, Steinhatchee, Oregon, 5491</TD><TD>banana</TD></TR></TABLE>

这篇关于JSON到CSV转换(JavaScript):如何正确设置CSV转换格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆