在Javascript中构建嵌套的JSON

时间:2017-03-30 01:49:52

标签: javascript arrays json javascript-objects

我想使用JavaScript或Angularjs或任何javascript库将此示例数据集复制到嵌套的JSON中。

数据:

PrimaryId,FirstName,LastName,City,CarName,DogName
100,John,Smith,NewYork,Toyota,Spike
100,John,Smith,NewYork,BMW,Spike
100,John,Smith,NewYork,Toyota,Rusty
100,John,Smith,NewYork,BMW,Rusty
101,Ben,Swan,Sydney,Volkswagen,Buddy
101,Ben,Swan,Sydney,Ford,Buddy
101,Ben,Swan,Sydney,Audi,Buddy
101,Ben,Swan,Sydney,Volkswagen,Max
101,Ben,Swan,Sydney,Ford,Max
101,Ben,Swan,Sydney,Audi,Max
102,Julia,Brown,London,Mini,Lucy

使用Javascript:

var file = reader.result; 
var singleRow = readerFile.split(/\r\n|\n/);
var header = singleRow[0].split(',');
var result =[];  

    for ( var i=1; i < file.length; i++ ){                                      
        var elementData = singleRow[i].split(',');                              
        elementData = elementData.filter(function(n){ return n != "" });        
        var Obj = {};                                                           

        for ( var j=0; j < header.length; j++ ){
            Obj[header[j]] = elementData[j];
            /*
              - How can i build child object and append back to Obj before j loop
              - How can i build multiple child for same parent 
            */                  
        }
        result.push(Obj);                                                       
    }
    console.log(" Print the JSON Object : " + JSON.stringify(result));

期望的输出:

{
    "data": [
        {
            "City": "NewYork", 
            "FirstName": "John", 
            "PrimaryId": 100, 
            "LastName": "Smith", 
            "CarName": [
                "Toyota", 
                "BMW"
            ], 
            "DogName": [
                "Spike", 
                "Rusty"
            ]
        }, 
        {
            "City": "Sydney", 
            "FirstName": "Ben", 
            "PrimaryId": 101, 
            "LastName": "Swan", 
            "CarName": [
                "Volkswagen", 
                "Ford", 
                "Audi"
            ], 
            "DogName": [
                "Buddy", 
                "Max"
            ]
        }, 
        {
            "City": "London", 
            "FirstName": "Julia", 
            "PrimaryId": 102, 
            "LastName": "Brown", 
            "CarName": [
                "Mini"
            ], 
            "DogName": [
                "Lucy"
            ]
        }
    ]
}

如果Firstname,Lastname和City具有相同的值,那么CarName和DogName值应该是同一父级下的子对象

3 个答案:

答案 0 :(得分:3)

首先,既然您已经知道了属性名称,那么解析第一行就没有意义了。

我会做这样的事情:

let results = {};
for (let i = 1; i < file.length; i++) {
  let entry = getEntry(results, file[i][0]);
  entry.DogName.push(file[i][DOGNAME_INDEX]);
  entry.CarName.push(file[i][CARNAME_INDEX]);
  entry.LastName = file[i][LASTNAME_INDEX];
  ...
}

// and now to convert this into an array
let array = Object.keys(results).map(key => results[key]);


// retrieves or creates an entry for a given primary key
function getEntry(results, id) {
  return results[id] || (results[id] = {});
}

您也可以更好地动态确定列索引是什么,但我拥有它的方式只是简单。

答案 1 :(得分:3)

我重新格式化了您的初始代码,但它并没有改变初始逻辑。一个关键的观察是,即使FirstNameLastNameCity相同,也可能不是一个独特的人,因此您应该使用PrimaryId代替确定唯一性。

查看新代码的后处理部分:

const data = `PrimaryId,FirstName,LastName,City,CarName,DogName
100,John,Smith,NewYork,Toyota,Spike
100,John,Smith,NewYork,BMW,Spike
100,John,Smith,NewYork,Toyota,Rusty
100,John,Smith,NewYork,BMW,Rusty
101,Ben,Swan,Sydney,Volkswagen,Buddy
101,Ben,Swan,Sydney,Ford,Buddy
101,Ben,Swan,Sydney,Audi,Buddy
101,Ben,Swan,Sydney,Volkswagen,Max
101,Ben,Swan,Sydney,Ford,Max
101,Ben,Swan,Sydney,Audi,Max
102,Julia,Brown,London,Mini,Lucy`;

var singleRow = data.split(/\r\n|\n/);
var header = singleRow[0].split(',');
var result =[];

for (var i = 1; i < singleRow.length; i++) {
  var elementData = singleRow[i].split(',');
  elementData = elementData.filter(function(n) { return n != '' });
  var Obj = {};
  for ( var j=0; j < header.length; j++ ){
    Obj[header[j]] = elementData[j];
  }
  result.push(Obj);
}

console.log(JSON.stringify(result, null, 2));


// Post-processing code starts here
const people = {};

// Create a map of unique people first
result.forEach(function (object) {
  if (!people[object.PrimaryId]) {
    people[object.PrimaryId] = {
      City: object.City,
      FirstName: object.FirstName,
      PrimaryId: object.PrimaryId,
      LastName: object.LastName,
      CarName: [],
      DogName: [],
    };
  }
  // As you iterate through your results, if this person already exists
  // add to their array of car and dogs.
  people[object.PrimaryId].CarName.push(object.CarName);
  people[object.PrimaryId].DogName.push(object.DogName);
});

// Convert back into an array
const peopleList = [];
Object.keys(people).forEach(function (primaryId) {
  peopleList.push(people[primaryId]);
})

console.log(peopleList);

答案 2 :(得分:2)

为你做了一个小提琴,它给出了所需的输出,其中一些东西的顺序与你呈现的顺序不同。

您可以保存标题的索引:

var Index = {};
for(var k = 0; k < header.length; k++)
{
    Index[header[k]] = k;
}

并保留一份城市列表:

var cities = [];
....
cities.push(data[Index["City"]]);

要稍后使用,以便在城市已存在的情况下不再制作更多对象:

obj = result.data[cities.indexOf(data[Index["City"]])];

JSFiddle:https://jsfiddle.net/3u28aon3/1/