如何使用数据分组将json数据转换为嵌套的json数据格式?

时间:2016-05-16 02:03:32

标签: javascript jquery json

我有一个json数组

[{
  id:1,
  topicid : 1,
  Topic:Topic_name,
  categoryid:1,
  category : category_name,
  subcategoryid:1,
  subcategory : subcategory_name,
  pageid: 1,
  pageurl : pageurl_name
}]

我想将json转换为下面的结构,你能不能请任何人使用jquery或JavaScript来帮助我。

[{
    id :1
    topicid:tiopicid,
    text: "topic_name",
    items: [{
       categoryid:categoryid,
       text: "category_name" ,                           
       items: [{
           subcategoryid:subcategoryid
           text: "subcategory_name"  ,                                    
           items: [{
                 pageid:pageid,
                 text: "pageurl_name"                                        
                  }]
              }]
       }]
}]

1 个答案:

答案 0 :(得分:0)

看起来您对(粗略地)规范化数据集感兴趣。在这种情况下,分组是任务。我清理了一些字段名称,以便更加一致和方便地使用这个特定的解决方案。

请注意,会阻止数据在不同的子组中重复。同样,如果原始数据跨不同主题复制<input type="text" id="qty_req_<?php echo $i; ?>" data-oldvalue="<?php echo $req; ?>" /> <script> $( document ).ready(function() { oldvalue = $("#qty_req_<?php echo $i; ?>").data('oldvalue'); }); </script> ,则两者都将写入每个主题(没有数据库连接或简单JSON中的引用)。这对您来说可能是也可能不是问题。

我使用了Ramda.js,这是一个功能强大的Javascript库。这也可以使用lodash,下划线甚至直接JS来完成。 jQuery不会帮助你;它主要是一个DOM兼容库。在代码之前的最后一个想法:使用循环执行此操作是完全可能的,但循环突变很棘手,尤其是这么多级别。

解决方案

任务是获取一组对象,每个对象具有相同的字段,并逐步将它们分组到容器对象中。每个对象包含原始id,id的名称和pageid个子对象的列表(最后一个id缺少此项目列表)id桶是:

items

因此,对于每个id,数据必须是:

  1. 分组成常见ID数组
  2. 已处理到容器对象
  3. 如果仍有任何ID,则所有子对象都会转储到var ids = ['topic', 'category', 'subcategory', 'page']; 中,并根据剩余的ID再次进行分组。
  4. 以下是相关代码:

    items

    (groupIdList, currentDataSet) => {
      var currentId = R.head(groupIdList);
      var remainingIds = R.tail(groupIdList);
    
      var groupedByCurrentId = R.pipe(
        R.groupBy(R.prop(currentId + 'id')),
        R.map((lst) => {
          // by definition, all elements in the list
          // will have the same id (and barring bad initial data,
          // the same root value) So the guaranteed exisiting first
          // element is used as a template
          var first = R.head(lst);
    
          // if ids remain, populate the items field
          var obj = remainingIds.length > 0 ? {
            items: groupBy(remainingIds, lst)
          } : {};
          obj[currentId + 'id'] = first[currentId + 'id'];
          obj[currentId] = first[currentId];
          return obj;
        }),
        // groupBy returns an object key/values, and map perserves this.
        // but this function only cares about the values at this point
        R.values
      )(currentDataSet);
      return groupedByCurrentId;
    };
    
    /* jshint esnext: true */
    
    var rawJson = [{
      "id": 1,
      "topicid": 1,
      "topic": "topic1",
      "categoryid": 1,
      "category": "cat1",
      "subcategoryid": 1,
      "subcategory": "subcat1",
      "pageid": 1,
      "page": "pageurl1"
    }, {
      "id": 2,
      "topicid": 1,
      "topic": "topic1",
      "categoryid": 1,
      "category": "cat1",
      "subcategoryid": 2,
      "subcategory": "subcat2",
      "pageid": 1,
      "page": "pageurl1"
    }, {
      "id": 4,
      "topicid": 1,
      "topic": "topic1",
      "categoryid": 1,
      "category": "cat1",
      "subcategoryid": 2,
      "subcategory": "subcat2",
      "pageid": 5,
      "page": "pageurl5"
    }, {
      "id": 3,
      "topicid": 2,
      "topic": "topic2",
      "categoryid": 4,
      "category": "cat4",
      "subcategoryid": 6,
      "subcategory": "subcat6",
      "pageid": 10,
      "page": "pageurl10"
    }];
    
    var groupBy = (groupIdList, currentDataSet) => {
      var currentId = R.head(groupIdList);
      var remainingIds = R.tail(groupIdList);
    
      var groupedByCurrentId = R.pipe(
        R.groupBy(R.prop(currentId + 'id')),
        R.map((lst) => {
          // by definition, all elements in the list
          // will have the same id (and barring bad initial data,
          // the same root value) So the guaranteed exisiting first
          // element is used as a template
          var first = R.head(lst);
    
          // if ids remain, populate the items field
          var obj = remainingIds.length > 0 ? {
            items: groupBy(remainingIds, lst)
          } : {};
          obj[currentId + 'id'] = first[currentId + 'id'];
          obj[currentId] = first[currentId];
          return obj;
        }),
        // groupBy returns an object key/values, and map perserves this.
        // but this function only cares about the values at this point
        R.values
      )(currentDataSet);
      return groupedByCurrentId;
    };
    
    var ids = ['topic', 'category', 'subcategory', 'page'];
    
    var output = groupBy(ids, rawJson);
    console.log(output);
    
    document.getElementById('results').innerText = JSON.stringify(output, null, 2);