2016-12-07 5 views
1

У меня есть массив с вложенными объектами, такими как этот:Как преобразовать массив вложенных объектов в CSV?

[ 
    {"name": "1", "children": [{"name": "1.1", "children":"1.2"}]}, 
    {"id": "2", "thing": [{"name": "2.1", "children":"2.2"}]}, 
    {"name": "3", "stuff": [{"name": "3.1", "children":"3.2"}]}, 
] 

Объекты могут содержать значения различных типов, в том числе других, вложенных друг в друга объектов.

Я хочу преобразовать этот массив в формат CSV.

Я пробовал итерацию с for .. in петлями, регулярными вложенными for петлями, .map() и рекурсией. Я думаю, что рекурсия может быть единственным способом решить эту конкретную проблему. Для имен полей CSV я хочу использовать последовательность ключей, которые приводят к значению.

Для данного примера, то CSV результата я ищу это:

name, children.name, children.children,id, thing.name, thing.children, stuff.name, stuff.children 
1, 1.1, 1.2, 
,,,2,2.1,2.2 
3,,,,3,3.1,3.2 
+0

[Там нет такого понятия, как объект JSON.] (Http://benalman.com/news/2010/03/theres-no-such-thing-as-a -json /) – nicovank

+1

А что, если у вас есть 2 вложенных 'children' объектов? – zerkms

+1

@nicovank - иди сюда, чтобы узнать ЧТО ТАКОЕ JSON ?? http://www.json.org/ – user1789573

ответ

4

Вы можете использовать эту функцию ES6 для создания 2D-массива, который вы ищете, которые затем можно легко преобразовать в CSV :

function pivot(arr) { 
 
    var mp = new Map(); 
 
    
 
    function setValue(a, path, val) { 
 
     if (Object(val) !== val) { // primitive value 
 
      var pathStr = path.join('.'); 
 
      var i = (mp.has(pathStr) ? mp : mp.set(pathStr, mp.size)).get(pathStr); 
 
      a[i] = val; 
 
     } else { 
 
      for (var key in val) { 
 
       setValue(a, key == '0' ? path : path.concat(key), val[key]); 
 
      } 
 
     } 
 
     return a; 
 
    } 
 
    
 
    var result = arr.map(obj => setValue([], [], obj)); 
 
    return [[...mp.keys()], ...result]; 
 
} 
 

 
function toCsv(arr) { 
 
    return arr.map(row => 
 
     row.map (val => isNaN(val) ? JSON.stringify(val) : +val).join(',') 
 
    ).join('\n'); 
 
} 
 

 
// Sample data 
 
var arr = [ 
 
    {"name": "1", "children": [{"name": "1.1", "children":"1.2"}]}, 
 
    {"id": "2", "thing": [{"name": "2.1", "children":"2.2"}]}, 
 
    {"name": "3", "stuff": [{"name": "3.1", "children":"3.2"}]}, 
 
]; 
 

 
// Conversion to 2D array and then to CSV: 
 
console.log(toCsv(pivot(arr)));
.as-console-wrapper { max-height: 100% !important; top: 0; }

для других способов преобразования 2D-массив в CSV, увидеть этот Q&A.

+0

спасибо большое! Я понятия не имел о функциональности JS-карты с эллипсами. – user1789573

0

Это предложение ES5.

Вы можете выполнить итерацию массива и собрать ключи в хеш-таблице и сохранить данные позже с помощью пробелов.

var data = [{ name: "1", children: [{ name: "1.1", children: "1.2" }] }, { id: "2", thing: [{ name: "2.1", children: "2.2" }] }, { name: "3", stuff: [{ name: "3.1", children: "3.2" }] }], 
 
    csv = function (array) { 
 
     var cols = [], 
 
      collection = Object.create(null), 
 
      i = -1, 
 
      toCSV = function (v) { return isNaN(v)? JSON.stringify(v): v; }, 
 
      csv; 
 

 
     array.forEach(function iter(path) { 
 
      return function (o) { 
 
       path.length || i++; 
 
       Object.keys(o).forEach(function (k) { 
 
        if (Array.isArray(o[k])) { 
 
         o[k].forEach(iter(path.concat(k))); 
 
         return; 
 
        } 
 
        var key = path.concat(k).join('.'); 
 
        if (!collection[key]) { 
 
         cols.push(key); 
 
         collection[key] = []; 
 
        } 
 
        collection[key][i] = o[k]; 
 
       }); 
 
      }; 
 
     }([])); 
 

 
     csv = cols.map(toCSV).join() + '\n'; 
 
     for (i = 0; i < array.length; i++) { 
 
      csv += cols.map(function (k) { return toCSV(collection[k][i]); }).join() + '\n'; 
 
     } 
 
     return csv; 
 
    }(data); 
 

 
console.log(csv);

Смежные вопросы