Javascript 将JSON转换为CSV,并将标头连接到父级

Javascript 将JSON转换为CSV,并将标头连接到父级,javascript,json,csv,Javascript,Json,Csv,我想将JSON响应转换为CSV格式。由于JSON响应可能不同,我无法手动创建我的头 我环顾四周,发现了一个关于堆栈溢出的编程解决方案。但是这个解决方案使用JSON的键作为头。我的测试数据是敏感的,因此我将发布一个类似的JSON响应,以更好地了解我正在尝试做什么 { "response":[{ "_id": "5cfe7d3c6deeeef08ce0444b", "name": "Debra Milligain", "phone": "+1 (906) 432-21

我想将JSON响应转换为CSV格式。由于JSON响应可能不同,我无法手动创建我的头

我环顾四周,发现了一个关于堆栈溢出的编程解决方案。但是这个解决方案使用JSON的键作为头。我的测试数据是敏感的,因此我将发布一个类似的JSON响应,以更好地了解我正在尝试做什么

{
    "response":[{
    "_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"
    }]}
从这里找到解决方案

这是实际的反应:

_id,name,phone,address,tags,Work,friends,greeting,favoriteFruit
"5cfe7d3c6deeeef08ce0444b","Debra Milligain","+1 (906) 432-2182","676 Merit Court, Steinhatchee, Oregon, 5491",["consequat","reprehenderit","amet"],{"skills":[{"id":0,"name":"Programming"},{"id":1,"name":"Business"}]},[{"id":0,"name":"Stafford Hernandez"},{"id":1,"name":"Colleen Christensen"},{"id":2,"name":"Barker Keith"}],[],"banana"
输出作为标题,但不包括子标题。实际输出应大致如此

"_id","name","phone","address","tags","Work__skills__id","Work__skills__name","friends__id","friends__name","favoriteFruit"
"5cfe7d3c6deeeef08ce0444b","Debra Milligain","+1 (906) 432-2182","676 Merit Court, Steinhatchee, Oregon, 5491","consequat","0","Programming","0","Stafford Hernandez","banana"
"","","","","reprehenderit","1","Business","1","Colleen Christensen",""
"","","","","amet","","","2","Barker Keith",""

我最终使用了自己的解决方案,只是递归地遍历JSON对象。我确保跟踪位于对象根的键值对和不位于对象根的键值对(因为我需要将它们的父名称附加到它们)。此外,我还使用了一个哈希表来确保没有重复的头,方法是将它们设置为键,并将它们的值作为头的实际值作为字符串附加,以
分隔 稍后将被解析。下面是代码,我决定将控制台日志留给其他人调试和理解流程

var arrayOfHeaders = {};
var headerDirectory = "";
var rootLevel = true;
var temp = ""
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;
            traverseJSON(obj[o]);
            rootLevel = true;
            temp = headerDirectory;
            headerDirectory = "";
        } else {
            if (rootLevel) {
                headerDirectory = "";
                //console.log("Has value and is root ", o)
                arrayOfHeaders[headerDirectory];
            }
            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)
}
我使用了问题中提供的相同样本数据,下面是运行该方法后
arrayOfHeaders
的内容

Array of Headers :  { '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"' }

希望这能帮助其他人解决类似的问题。

关于构造函数中隐藏递归的更面向对象的方法呢

madeiterator-您可以迭代4个方向(next、prev、node、parent)以及示例数据的2次演示遍历(日志对于单个输出来说太长)

如果您从迭代器中获得私有的当前JNode,您可以在任何可以检查变量的调试器中列出该容器结构(例如VSC&node.js)

单独的IIFE代码在第三个框中

深度第一演示:

“严格使用”;
功能测试(json){
var it=新的JIterator(json);
var i=0;
var htmlTable=“#LevelPathKeyValue或Type”;
做{
htmlTable+=“”;
htmlTable++=[i++,it.Level,it.Path().join('..),it.KeyDots(),(对象的it.Value()实例)?(数组的it.Value()实例?[]:“{}”):it.Value()]join(“”);
htmlTable+=“”;
}而(it.DepthFirst());
htmlTable+=“”;
document.body.innerHTML=htmlTable;
}
var JNode=(函数(jsNode){
函数JNode(_parent,_pred,_key,_value){
this.parent=\u parent;
this.pred=_pred;
this.node=null;
this.next=null;
this.key=\u key;
this.value=_值;
}
返回JNode;
})();
var JIterator=(函数(json){
变量根,当前,maxLevel=-1;
函数JIterator(json,父级){
如果(parent==未定义)parent=null;
var pred=null,localCurrent;
for(json中的var子级){
var obj=json[child]instanceof Object;
if(json instanceof Array)child=parseInt(child);//非关联数组
如果(!root)root=localCurrent=newjnode(父、空、子、json[child]);
否则{
localCurrent=newjnode(父、pred、子、obj?((json[child]instanceof Array)?[]:{}):json[child]);
}
如果(pred)pred.next=localCurrent;
如果(parent&&parent.node==null)parent.node=localCurrent;
pred=本地电流;
如果(obj){
var memPred=pred;
JIterator(json[child],pred);
pred=memPred;
}
}
如果(这个){
电流=根;
这个水平=0;
}
}
JIterator.prototype.Current=函数(){return Current;}
JIterator.prototype.Parent=函数(){
var retVal=current.parent;
如果(retVal==null)返回false;
这是一级;
返回电流=返回值;
}
JIterator.prototype.Pred=函数(){
var retVal=current.pred;
如果(retVal==null)返回false;
返回电流=返回值;
}
JIterator.prototype.Node=函数(){
var retVal=current.node;
如果(retVal==null)返回false;
这个.Level++;
返回电流=返回值;
}
JIterator.prototype.Next=函数(){
var retVal=current.next;
如果(retVal==null)返回false;
返回电流=返回值;
}
JIterator.prototype.Key=函数(){return current.Key;}
JIterator.prototype.KeyDots=function(){return(typeof(current.key)=“number”)?:(current.key+':');}
JIterator.prototype.Value=函数(){return current.Value;}
JIterator.prototype.Reset=函数(){
电流=根;
这个水平=0;
}
JIterator.prototype.RawPath=函数(){
var步骤=[],级别=当前;
做{
if(level!=null&&level.value对象实例){
push(level.key+(数组的level.value实例?[]:“{}”);
}否则{
如果(level!=null)步进。推(level.key);
否则就断了;
}
level=level.parent;
}while(level!=null);
var retVal=“”;
retVal=steps.reverse();
返回返回;
}
JIterator.prototype.Path=函数(){
var步骤=[],级别=当前;
做{
if(level!=null&&level.value对象实例){
变量大小=0;
var items=level.node;
如果(typeof(level.key)=“number”)步数按('['+level.key+']');
否则{
while(项目){
大小++;
items=items.next;
}
变量类型=(数组的level.value实例?[]:“{}”);
var prev=步数[steps.length-1];
如果(上一个和上一个[0]='['){
最后一个变量=上一个长度
Array of Headers :  { '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"' }