【问题标题】:How to convert not nested JSON into nested HTML list in Javascript (or Coffeescript)?如何将未嵌套的 JSON 转换为 Javascript(或 Coffeescript)中的嵌套 HTML 列表?
【发布时间】:2013-03-17 11:10:22
【问题描述】:

我有一些 JSON 数据(简单的对象数组)。

var input= [
    {
        "cat": "some",
        "id": "0"
    },
    {
        "cat": "some",
        "id": "1"
    },
    {
        "cat": "some/category",
        "id": "2"
    },
    {
        "cat": "some/category/sub",
        "id": "3"
    },
    {
        "cat": "some/other",
        "id": "4"
    },
    {
        "cat": "some/thing/different",
        "id": "5"
    },
    {
        "cat": "some/thing/different",
        "id": "6"
    },
    {
        "cat": "yet/another",
        "id": "7"
    }
]

我想根据类别从中生成嵌套的 html 列表:

  • 一些
    • 0
    • 1
    • 类别
      • 2
        • 3
    • 其他
      • 4
    • 东西
      • 不同
        • 5
        • 6
    • 另一个
      • 7

我的第一步是使用函数创建空的嵌套对象:

createNestedObject = function(base, names) {
  var  = 0;
  var results = [];
  while (i < names.length) {
    base = base[names[i]] = base[names[i]] || {};
    results.push(i++);
  }
  return results;
}

接下来,我通过拆分“cat”字符串并在循环中推送“ids”来填充数据(例如 some.category.sub.ids.push(7)) 最终结果是:

var output = 
{
    "some": {
        "ids": [
            "0",
            "1"
        ],
        "category": {
            "ids": [
                "2"
            ],
            "sub": {
                "ids": [
                    "3"
                ]
            }
        },
        "other": {
            "ids": [
                "4"
            ]
        },
        "thing": {
            "different": {
                "ids": [
                    "5",
                    "6"
                ]
            }
        },
        "yet": {
            "another": {
                "ids": [
                    "7"
                ]
            }
        }
    }
}

但是,结构有些问题,因为我事先不知道键名和嵌套深度。 如何从此处显示的“输出”或“输入”数据生成嵌套的 html 列表?

【问题讨论】:

    标签: javascript jquery arrays json coffeescript


    【解决方案1】:

    这个怎么样?

    Example

    JS

    function ToHTML(input){
        var html = '<ul>'; 
    
        for(var key in input){
            if(input[key] instanceof Array){
                for(var i = 0; i < input[key].length; i++){
                    html += '<li>' + input[key][i] + '</li>';
                }
            }else{
                html += '<li>' + key + ToHTML(input[key]) + '</li>';
            }           
        }
        html += '</ul>';
        return html; 
    }
    
    function ToNestedObject(input){
        var i, y, len = input.length, parts, partsLen, obj = {}, prev;
        for(i = 0; i < len; i++){
            parts = input[i].cat.split('/'); 
            partsLen = parts.length;
            prev = obj; 
            for(y = 0; y < partsLen; y++){
                prev[parts[y]] = prev[parts[y]] || {};    
                prev = prev[parts[y]];
            }
            if(!prev.ids){
                prev.ids = []; 
            }
            prev.ids.push(input[i].id); 
        }
        return obj; 
    }
    
    var input= [
        {
            "cat": "some",
            "id": "0"
        },
        {
            "cat": "some",
            "id": "1"
        },
        {
            "cat": "some/category",
            "id": "2"
        },
        {
            "cat": "some/category/sub",
            "id": "3"
        },
        {
            "cat": "some/other",
            "id": "4"
        },
        {
            "cat": "some/thing/different",
            "id": "5"
        },
        {
            "cat": "some/thing/different",
            "id": "6"
        },
        {
            "cat": "yet/another",
            "id": "7"
        }
    ];
    
    document.getElementById('test').innerHTML = ToHTML(ToNestedObject(input)); 
    

    HTML

    <div id='test'></div>
    

    【讨论】:

      【解决方案2】:

      数组转化为对象树

      function buildTreeObject ( input ) {
      
              var obj = {}, n ;
      
              input.forEach( function( v ){
                      var keys = v.cat.split('/'),
                          n = obj ;        
      
                      keys.forEach( function( k ){        
                              if ( !n[k]) {
                                  n[k] = {}; 
                              }                 
                              n = n[k];                 
                      }); 
      
                      n[ v.id ] = v.id ;                
              });
      
              return obj;
      }
      

      我们需要一个函数来构建 html

      function buildHtml( obj , ul ) {
      
          for (i in obj) {
      
              var li = document.createElement('li');
              li.innerHTML = i;
              ul.appendChild( li );
      
              if ( typeof(obj[i])== "object" ) {
      
                  childUl = document.createElement('ul');
                  li.appendChild( childUl ); 
      
                  buildHtml(obj[i], childUl );            
              }  
      
          }
      } 
      

      并让 html 使用input(即你的数组)

      var ul   = document.createElement('ul'),
          tree =  buildTreeObject( input ) ;
      
      buildHtml( tree ,ul );
      
      var div = document.createElement('div');    
      div.appendChild( ul );
      
      console.log( div.innerHTML );
      

      打印所需的 ul li 列表

      你可以在http://jsfiddle.net/r3RWL/看到结果

      【讨论】:

      • 感谢您的解决方案。
      【解决方案3】:

      由于您在标签下添加了 jquery,我已经在 jQuery 中为您的问题编写了解决方案。代码如下:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      <html>
          <head>
              <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
          </head>
      <body>
          <div id="someDiv">
          </div>
          <script>
      
          function prepareNestedStructure(input) {
              var output = {},
                  catLevels,
                  currentCat;
      
              $.each(input, function(index, catObject) {
                  catLevels = catObject.cat.split('/');
                  currentCat = output;
      
                  $.each(catLevels, function(index, name) {
                      if(!currentCat[name])
                          currentCat[name] = {};
                      currentCat = currentCat[name];
                  });
      
                  currentCat[catObject.id] = catObject.id;
              });
      
              return output;
          }
      
          function fillList(parentListEl, node) {
              $.each(node, function(key, value) {
                  parentListEl.append('<li>' + key + '</li>');
      
                  if(jQuery.type(value) === 'object') {
                      var childEl = $('<ul></ul>');
                      parentListEl.append(childEl);
                      fillList(childEl, value);
                  }
              });
          }
      
          var input= [
              {
                  "cat": "some",
                  "id": "0"
              },
              {
                  "cat": "some",
                  "id": "1"
              },
              {
                  "cat": "some/category",
                  "id": "2"
              },
              {
                  "cat": "some/category/sub",
                  "id": "3"
              },
              {
                  "cat": "some/other",
                  "id": "4"
              },
              {
                  "cat": "some/thing/different",
                  "id": "5"
              },
              {
                  "cat": "some/thing/different",
                  "id": "6"
              },
              {
                  "cat": "yet/another",
                  "id": "7"
              }
          ];
      
          var output = prepareNestedStructure(input);
      
          var ulDomElement = $('<ul></ul>');
          fillList(ulDomElement, output);
          $('#someDiv').append(ulDomElement);
      
          </script>
      </body>
      </html>
      

      【讨论】:

      • 谢谢 - jQuery 解决方案也可以。
      【解决方案4】:

      这个呢?

      transform_deeply_nested_object = (dno) ->
          result = ""
          for key, value of dno
              if value instanceof Array
                  result += "<ul>"
                  for elem in value
                      result += "<li>" + elem + "</li>\n"
                  result += "</ul>"
              else
                  result += "<ul><li>" + key + "</li>"
                  result += transform_deeply_nested_object value
                  result += "</ul>"
      

      注意:未经测试!

      注意:这要求所有叶子始终是数组的元素。

      【讨论】:

      • 谢谢,很遗憾,输出不是很准确,但问题已经解决了。
      猜你喜欢
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 2021-10-23
      • 2014-08-04
      • 2021-11-25
      • 1970-01-01
      • 2020-09-03
      相关资源
      最近更新 更多