展平(种类)JSON数据

时间:2016-03-16 21:37:51

标签: jquery json

我有以下数组:

var data = {
    menu: [{
        name: 'Step 1',
        sub: [{
            name: 'Step 1 sub A',
            sub: null
        }, {
            name: 'Step 1 sub B',
            sub: null
        }, {
            name: 'Step 1 sub C',
            sub: [{
                name: 'Step 1 sub C sub A',
                sub: null
            }, {
                name: 'Step 1 sub C sub B',
                sub: [{
                    name: 'Step 1 sub C sub B sub A',
                    sub: null
                }, {
                    name: 'Step 1 sub C sub B sub B',
                    sub: null
                }]
            }]
        }]
    }, {
        name: 'Step 2',
        sub: [{
            name: 'Step 2 sub A',
            sub: null
        }, {
            name: 'Step 2 sub B',
            sub: [{
                name: 'Step 2 sub B sub A',
                sub: null
            }, {
                name: 'Step 2 sub B sub B',
                sub: null
            }, {
                name: 'Step 2 sub B sub C',
                sub: null
            }]
        }, {
            name: 'Step 2 sub B',
            sub: null
        }]
    }]
};

我想要归还的是例如。

Step 1
Step 1 > Step 1 sub A
Step 1 > Step 1 sub B
Step 1 > Step 1 sub C
Step 1 > Step 1 sub C > Step 1 sub C sub A
Step 1 > Step 1 sub C > Step 1 sub C sub B
etc. etc.

这就是我正在尝试的:

var $menu = $("#menu");

var getMenuItem = function (data) {

    var item = data.name; // start

    if (data.sub) { // if we have subs concat them
        var subList = '';
        $.each(data.sub, function () {
            subList =+ getMenuItem(this) + ' > ';
        });
        item = item + ' > ' + subList;
    }
    return item; // now return it
};

$.each(data.menu, function () {
    $menu.append(
        getMenuItem(this) + '<br />'
    );
});

但所有这一切都是:

Step 1 > NaN > 
Step 2 > NaN > 

我该如何处理?

Here's a fiddle to show the code

3 个答案:

答案 0 :(得分:2)

您可以通过简单的递归功能实现此目的。您需要首先为当前级别创建li,然后检查sub项目,然后通过这些项目进行递归,然后追加。试试这个:

function menuFromObject(prev, m) {  
    $.each(m, function(i, menu) {
        var itemName = prev + (prev.length ? ' > ' : '') + menu.name;
        $('#menu').append('<li>' + itemName + '</li>');        
        if (menu.sub && menu.sub.length) 
            menuFromObject(itemName, menu.sub);
    });
}

menuFromObject('', data.menu);

Working example

答案 1 :(得分:0)

递归方法绝对是最好的选择。以下是针对您的用例的一些内容,但可以正常使用。

function flatten(prefix, data) {
  for(var attr in data) {
    var n = data.name ? data.name + ' > ' : '';
    if(typeof data === 'object') flatten(prefix + n, data[attr])
    else console.log(prefix + n)
  }
}

// Hacky way is just to feed it a blank string to start
flatten('', data)

这是一个提出概念的JSFiddle。显然它可以改进和定制,但它是一种非常简洁的方法,可以从这样的数据中删除维度。

答案 2 :(得分:0)

这是一个递归功能,可以完成我认为你需要的功能。请注意,我打破了第一层以避免以下情况:

  

步骤1&gt;步骤1子C>步骤1子C sub B>步骤1子C sub B sub B &gt;第2步

演示:

var data = {
  menu: [{
    name: 'Step 1',
    sub: [{
      name: 'Step 1 sub A',
      sub: null
    }, {
      name: 'Step 1 sub B',
      sub: null
    }, {
      name: 'Step 1 sub C',
      sub: [{
        name: 'Step 1 sub C sub A',
        sub: null
      }, {
        name: 'Step 1 sub C sub B',
        sub: [{
          name: 'Step 1 sub C sub B sub A',
          sub: null
        }, {
          name: 'Step 1 sub C sub B sub B',
          sub: null
        }]
      }]
    }]
  }, {
    name: 'Step 2',
    sub: [{
      name: 'Step 2 sub A',
      sub: null
    }, {
      name: 'Step 2 sub B',
      sub: [{
        name: 'Step 2 sub B sub A',
        sub: null
      }, {
        name: 'Step 2 sub B sub B',
        sub: null
      }, {
        name: 'Step 2 sub B sub C',
        sub: null
      }]
    }, {
      name: 'Step 2 sub B',
      sub: null
    }]
  }]
};

var name = '';
var el = document.querySelector('pre');

function output(s){
  //console.log(s);
  el.appendChild(document.createTextNode(s));
  el.appendChild(document.createElement('br'));
}

function flatten(menu){
  for(var i = 0, len = menu.length; i < len; i++) {
    var result = (name += ' > ' + menu[i].name);
    output(result);
    if(menu[i].sub)
      flatten(menu[i].sub);
    else 
      name = name.replace(/[\s>]+[^>]+?$/, '');
  }
}
for(var i = 0, len = data.menu.length; i < len; i++) {
  name = data.menu[i].name;
  output(name);
  flatten(data.menu[i].sub);
}
<pre></pre>