【问题标题】:Build nested JSON in Javascript在 Javascript 中构建嵌套的 JSON
【发布时间】:2017-03-30 01:49:51
【问题描述】:

我想使用 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 值应该是同一父级下的子对象

【问题讨论】:

  • There's no such thing as a "JSON object". 无论如何,它只是应该用于分组数据的PrimaryId 字段吗?也就是说,假设给定 ID 将始终具有相同的名字和姓氏和城市是否安全,或者这些字段也可能最终成为给定 ID 中的数组?一个完全通用的解决方案需要允许任何重复的字段,但如果它只有两个特定字段并且字段名称始终相同,那么不太通用的代码可能会更简单。
  • 我不知道正确和详细的答案,但我认为您应该查看 hashmap 或 hashtable 数据结构,其中具有特定键的对象只能出现一个。只需遍历所有行并搜索 id,如果不存在,则创建一个新的。然后根据它是单值还是多值来更新或添加所有其他字段。
  • @nnnnnn 谢谢你,我纠正了我的问题。是的,我们可以假设 3 列条目是相同的

标签: javascript arrays json javascript-objects


【解决方案1】:

我稍微重新格式化了您的初始代码,但它并没有改变初始逻辑。一个关键的观察结果是,即使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);

【讨论】:

  • 谢谢你,你将如何构建 CarName 的对象而不是仅仅附加值?例如` CarName: [ "type1":"Volkswagen", "type2:"Ford", "type3":"Audi" ] `
【解决方案2】:

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

我会这样做:

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] = {});
}

您还可以更高级地动态确定列索引是什么,但我拥有它的方式只是让事情变得简单。

【讨论】:

    【解决方案3】:

    为您制作了一个小提琴,它以与您呈现的顺序不同的顺序提供了所需的输出。

    您可以保存标题的索引:

    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/

    【讨论】:

      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 2022-08-18
      • 2012-12-22
      • 2017-02-14
      • 2015-05-09
      • 2013-03-15
      • 2017-10-25
      相关资源
      最近更新 更多