重新格式化分层JSON数据

时间:2018-04-03 16:20:38

标签: javascript jquery

我使用PHP从PostgreSQL数据库中检索以下分层JSON数据:

[{"treelevel":"1","app":"Front","lrflag":null,"ic":null,"price":null,"parentlevel":"0","seq":"27", "indexlistid":439755},
{"treelevel":"2","app":"V-Series","lrflag":null,"ic":null,"price":null,"parentlevel":"1","seq":"28", "indexlistid":439755},
{"treelevel":"3","app":"opt J56","lrflag":null,"ic":null,"price":null,"parentlevel":"2","seq":"29", "indexlistid":439755},
{"treelevel":"4","app":"R.","lrflag":"R","ic":"536-01132AR","price":"693.00","parentlevel":"3","seq":"30", "indexlistid":439755},
{"treelevel":"4","app":"L.","lrflag":"L","ic":"536-01133AL","price":"693.00","parentlevel":"3","seq":"31", "indexlistid":439755},
{"treelevel":"3","app":"opt J63","lrflag":null,"ic":null,"price":null,"parentlevel":"2","seq":"32", "indexlistid":439755},
{"treelevel":"4","app":"R.","lrflag":"R","ic":"536-01130R","price":null,"parentlevel":"3","seq":"33", "indexlistid":439755},
{"treelevel":"4","app":"L.","lrflag":"L","ic":"536-01131L","price":null,"parentlevel":"3","seq":"34", "indexlistid":439755}]

我需要一些方法将数据重新格式化为:

[{"app": "Front-V-Series-opt J56-R. R", "price": "$693", "ic": "536-01132AR"},
{"app": "Front-V-Series-opt J56-L. L", "price": "$693", "ic": "536-01132AL"},
{"app": "Front-V-Series-opt J63-R. R", "price": null, "ic": "536-01130R"},
{"app": "Front-V-Series-opt J63-L. L", "price": null, "ic": "536-01131L"}]

parentlevel和treelevel是构成树关系的2个键。

新格式的app值是来自所有的app和lrflag值的串联 一个树级别的节点+级别中最深叶子节点的价格和ic。这是 数据可视化为树:

[
    {
        "app": "Front",
        "children": [
            {
                "app": "V-Series",
                "children": [
                    {
                        "app": "opt J56",
                        "children": [
                            {
                                "app": "R. ,
                                "lrflag": "R",
                                "ic": "536-01132AR",
                                "price": "$693"
                            },
                            {
                                "app": "L. ,
                                "lrflag": "L",
                                "ic": "536-01132AL",
                                "price": "$693"
                            }
                        ]
                    },
                    {
                        "app": "opt J63",
                         "children": [
                            {
                                "app": "R. ,
                                "lrflag": "R",
                                "ic": "536-01130R"
                            },
                            {
                                "app": "L. ,
                                "lrflag": "L",
                                "ic": "536-01131L"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

我已经尝试了几种不同的方法来做到这一点,但我只是卡住了。以下是一些功能 我试图修改和使用没有运气。我甚至无法正确地构建树 这些

function buildTree(list) {
    var map = {}, node, roots = [], i;
    for (i = 0; i < list.length; i += 1) {
        map[list[i].treelevel] = i; // initialize the map
        list[i].children = []; // initialize the children
    }
    for (i = 0; i < list.length; i += 1) {
        node = list[i];
        if (node.parentlevel !== "0") {
            // if you have dangling branches check that map[node.parentId] exists
            list[map[node.parentlevel]].children.push(node);
        } else {
            roots.push(node);
        }
    }
    return roots;
}

function listToTree(data, options) {
    options = options || {};
    var ID_KEY = options.idKey || 'treelevel';
    var PARENT_KEY = options.parentKey || 'parentlevel';
    var CHILDREN_KEY = options.childrenKey || 'children';

    var tree = [],
        childrenOf = {};
    var item, id, parentId;

    for (var i = 0, length = data.length; i < length; i++) {
        item = data[i];
        id = item[ID_KEY];
        parentId = item[PARENT_KEY] || 0;
        // every item may have children
        childrenOf[id] = childrenOf[id] || [];
        // init its children
        item[CHILDREN_KEY] = childrenOf[id];
        if (parentId != 0) {
            // init its parent's children object
            childrenOf[parentId] = childrenOf[parentId] || [];
            // push it into its parent's children object
            childrenOf[parentId].push(item);
        } else {
            tree.push(item);
        }
    };

    return tree;
}

unflattenToObject = function(array, parent) {
    var tree = {};
    parent = typeof parent !== 'undefined' ? parent : {id: 0};

    var childrenArray = array.filter(function(child) {
        return child.treelevel == parent.parentlevel;
    });

    if (childrenArray.length > 0) {
        var childrenObject = {};
        // Transform children into a hash/object keyed on token
        childrenArray.forEach(function(child) {
            childrenObject[child.treelevel] = child;
        });
        if (parent.treelevel == 0) {
            tree = childrenObject;
        } else {
            parent['children'] = childrenObject;
        }
        childrenArray.forEach(function(child) {
            unflattenToObject(array, child);
        })
    }
    return tree;
};

1 个答案:

答案 0 :(得分:0)

这个想法是在最大深度treelevel : 4中得到第一个元素的索引,然后从那里开始并向后循环,确保你不会经历两次父母,并连接什么你需要一路走来,一旦你到达顶层,就删除那个元素

将它包装在一个函数中并递归调用它,直到没有treelevel : 4离开

&#13;
&#13;
var data = [{
    "treelevel": "1",
    "app": "Front",
    "lrflag": null,
    "ic": null,
    "price": null,
    "parentlevel": "0",
    "seq": "27",
    "indexlistid": 439755
  },
  {
    "treelevel": "2",
    "app": "V-Series",
    "lrflag": null,
    "ic": null,
    "price": null,
    "parentlevel": "1",
    "seq": "28",
    "indexlistid": 439755
  },
  {
    "treelevel": "3",
    "app": "opt J56",
    "lrflag": null,
    "ic": null,
    "price": null,
    "parentlevel": "2",
    "seq": "29",
    "indexlistid": 439755
  },
  {
    "treelevel": "4",
    "app": "R.",
    "lrflag": "R",
    "ic": "536-01132AR",
    "price": "693.00",
    "parentlevel": "3",
    "seq": "30",
    "indexlistid": 439755
  },
  {
    "treelevel": "4",
    "app": "L.",
    "lrflag": "L",
    "ic": "536-01133AL",
    "price": "693.00",
    "parentlevel": "3",
    "seq": "31",
    "indexlistid": 439755
  },
  {
    "treelevel": "3",
    "app": "opt J63",
    "lrflag": null,
    "ic": null,
    "price": null,
    "parentlevel": "2",
    "seq": "32",
    "indexlistid": 439755
  },
  {
    "treelevel": "4",
    "app": "R.",
    "lrflag": "R",
    "ic": "536-01130R",
    "price": null,
    "parentlevel": "3",
    "seq": "33",
    "indexlistid": 439755
  },
  {
    "treelevel": "4",
    "app": "L.",
    "lrflag": "L",
    "ic": "536-01131L",
    "price": null,
    "parentlevel": "3",
    "seq": "34",
    "indexlistid": 439755
  }
];

// first go look for the max depth in the tree, if it's always four, skip this part and put var max = 4

var max = 0;

data.forEach(function(elem) {
  if (elem.treelevel >= max)
    max = elem.treelevel;
});

// implement a function to get the index of the first matched element with treelevel = max depth

function getIndex() {
  return data.indexOf(data.find((elem) => {
    return elem.treelevel == max;
  }));
}

var myTree = [];

function formObject(ndx) {
  var myObj = {};
  myObj.app = [];
  var nextTreeLevel = 3;

  // start looping from the index of the element in max depth backwards 

  for (var i = ndx; i >= 0; i--) {
    // if the next element ( backwards ) is a parent , this is to avoid going through parent's siblings
    if (nextTreeLevel == data[i].parentlevel) {
      if (data[i].ic != null) myObj.ic = data[i].ic;
      if (data[i].price != null) myObj.price = data[i].price;
      if (data[i].lrflag != null) myObj.app.push(data[i].lrflag);

      myObj.app.push(data[i].app);

      nextTreeLevel = data[i].parentlevel - 1; // prent's level
    }
  }

  data.splice(ndx, 1); // remove the lement once you're done with it

  // glue the "app" together, would be better to use array.join but it's not the same join everywhere
  myObj.app = myObj.app[4] + '-' + myObj.app[3] + '-' + myObj.app[2] + '-' + myObj.app[1] + ' ' + myObj.app[0];

  // just to fill the price with null if there is none
  if (myObj.price == undefined) myObj.price = null;

  // push the object to the result's array
  myTree.push(myObj);

  // get the index of the next element in max depth ( 4 ) 
  var nextIndex = getIndex();

  // if there's still another element in the max depth, recall the same function with it's index
  if (nextIndex > -1)
    formObject(nextIndex)
}

formObject(getIndex())

console.log(myTree);
&#13;
&#13;
&#13;