jQuery 树遍历 - 将无序列表元素嵌套到 JSON

Posted

技术标签:

【中文标题】jQuery 树遍历 - 将无序列表元素嵌套到 JSON【英文标题】:jQuery tree traversal - Nested Unordered list elements to JSON 【发布时间】:2010-07-03 20:22:12 【问题描述】:

好的,现在我这里有一个无序列表:

<ul id="mycustomid">
    <li><a href="url of Item A" title="sometitle">Item A</a>
        <ul class="children">
           <li><a href="url of Child1 of A" title="sometitle">Child1 of A</a>
               <ul class="children">
                 <li><a href="url of Grandchild of A" title="sometitle">Grandchild of A</a>
                    <ul class="children">
                       <li><a href="url of Grand Grand child of A" title="sometitle">Grand Grand child of A</a></li>
                    </ul>
                </li>
               </ul>
           </li>
        </ul>
    </li>
    <li><a href="url of Item B" title="sometitle">Item B</a></li>
    <li><a href="url of Item C" title="sometitle">Item C</a></li>
</ul>

基本上,我只想将此数据转换为 JSON 实体。我想在 jQuery 中完成这项工作,而且我认为我很难做到。上面的列表只是一个例子,实际上,我的列表理想情况下会有更多的孩子,并且可能有“n”级深(意思是,它会有孙子的孙子的孙子孙女......或更多)我已经失去了无数睡了几个小时,我想我哪儿也不去:(

我想提取这些东西:锚点内的文本、锚点的url和锚点的标题,并将它们放到一个JSON实体上

我上面的列表的 JSON 格式是这样的:


        name: "Item A",
        url: "url of Item A",
        title: "sometitle",
        children: [
                   name: "Child1 of A",
                   url: "url of Child1 of A",
                   title: "sometitle",
                   children: [
                                name: "Grandchild of A",
                                url: "url of Grandchild of A",
                                title: "sometitle",
                                children: [
                                           name: "Grand Grand child of A",
                                           url: "url of Grand Grand child of A",
                                           title: "sometitle",
                                           children: []
                                           ]
                              ]
                   ]
,
           
            name: "Item B",
            url: "url of Item B",
            title: "sometitle",
            children: []
           ,
           
            name: "Item C",
            url: "url of Item C",
            title: "sometitle",
            children: []
           

一些有用的参考资料:

Javascript 解决方案: Traversing unordered lists using javascript/Jquery

^ 这可能有效,但我需要的 JSON 输出格式如上所示,而不是此脚本输出的格式:(

其他参考资料:

How do I put unordered list items into an array

https://jsfiddle.net/yS6ZJ/1/

https://jsfiddle.net/CLLts/

https://jsfiddle.net/cWnwt/

请大家帮忙:( 很多个不眠之夜都让我头疼..(P.s - 我花了大约 40 多分钟的时间来编写整个页面以及代码)

【问题讨论】:

正在处理它。顺便说一句,您生成的 JSON 是一个对象数组,因此您应该有周围的 [ 和 ] 括号。 [ , , ] 谢谢 Samuel,但我的应用程序似乎使用了无效的 JSON,并且它使用了上述格式 :) 感谢您的输入 :) 【参考方案1】:

啊,一个有趣的小递归练习。我有一点时间,这就是我将如何做到的。这可以递归地工作很多层次,但假设您的数据不够深而无法爆炸内存(如果太深,浏览器中的递归会中断)。至少10级左右应该没问题。

我已经测试过了,似乎它可以工作,只需将它保存在 html 文件中就可以了。

抱歉,没有太多的 cmets(嗯,从技术上讲,根本没有 :),这假设您可以很好地阅读 jQuery 和 JS 代码。如果您有任何问题,请在评论中提问,我很乐意为您解释。

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>Recursive list processor example</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
    <script type="text/javascript">

$(document).ready(function() 

    var out = [];

    function processOneLi(node)        

        var aNode = node.children("a:first");
        var retVal = 
            "title": aNode.attr("title"),
            "url": aNode.attr("href"),
            "name": aNode.text()
        ;

        node.find("> .children > li").each(function() 
            if (!retVal.hasOwnProperty("children")) 
                retVal.children = [];
            
            retVal.children.push(processOneLi($(this)));
        );

        return retVal;
    

    $("#mycustomid").children("li").each(function() 
        out.push(processOneLi($(this)));
    );


    console.log("got the following JSON from your HTML:", JSON.stringify(out));

);

    </script>
</head>
<body>
<ul id="mycustomid">
    <li><a href="http://example.com/urlOfItemA" title="sometitle">Item A</a>
        <ul class="children">
           <li><a href="http://example.com/urlOfItemAChild1" title="sometitle">Child1 of A</a>
               <ul class="children">
                 <li><a href="http://example.com/urlOfItemAGrandchild" title="sometitle">Grandchild of A</a>
                    <ul class="children">
                       <li><a href="http://example.com/urlOfItemAGrandGrandChild" title="sometitle">Grand Grand child of A</a></li>
                    </ul>
                </li>
               </ul>
           </li>
        </ul>
    </li>
    <li><a href="http://example.com/urlOfItemB" title="sometitle2">Item '"" B</a></li>
    <li><a href="http://example.com/urlOfItemC" title="sometitle3">Item C</a></li>
</ul>
</body>
</html>

【讨论】:

抱歉,Jaanus,我不在办公桌前。非常感谢您的努力,您提供的代码简直完美无缺,您是我变相的祝福,您为我省去了很多头痛!非常感谢!!! :) 你也应该标记接受的答案,无论你接受哪个,成为一个好的 *** 公民:) 但是,它没有以我的格式输出 JSON?例如,我在属性上有引号,例如:“name”:“something”“title”:“something”相反,我需要它像name:“something”title:“something”谢谢 JSON 标准规定对象键必须用双引号括起来。我正在使用 Douglas Crockford 的标准 JSON 输出器,这是将 Javascript 对象转换为 JSON 字符串的行业标准。因此,您要求的是非标准的无效 JSON。为什么需要它? 1) 不用担心,我们曾经都是新手 :) 2) 我明白你的意思。像 JSON 这样的标准的要点是应用程序以标准方式输入和输出它。正确的做法是修复您的应用程序,使其接受标准的有效 JSON。如果那不可能,您也许可以让 tvanfonsson 的代码工作。您可以看到它如何将自定义 JSON 输出为字符串,并且您可以修改它来生成您需要的内容。但实际上,您应该修复这个其他应用程序。还有其他方法,但它们确实是倒退的坏习惯。【参考方案2】:

似乎使用一个函数用于列表元素(子)集合和一个用于列表元素的递归解决方案将起作用。请注意,我假设您希望将其格式化为字符串,并且它实际上表示为数组。

$(function() 
    var json = formatListElements( $('#mycustomid > li') );
);

function formatListElements( elems )

    var contents = [] 
    $.each( elems, function( index, elem ) 
        contents[index] = formatListElement( elem );
    
    return '[' + contents.join(', ') + ']';


function formatListElement( elem )

   var anchor = $(elem).children('a:first');
   return ' "name": "' + quote( anchor.text() )
                + '", "url": "' + quote( anchor.attr('href') )
                + '", "title": "' + quote( anchor.attr('title') )
                + '", "children": ' + formatListElements( $(elem).find('> ul > li')
        + '';


function quote( str )

    return str.replace( /"/g, '\\\"' );

【讨论】:

这会输出无效的 JSON,因为:1) 你没有引用属性值 2) 你没有转义字符串中的 ' 或 " 字符,你会引用属性值。否则很好。跨度> @Jaanus -- 是的,只是一个快速的答案并且完全未经测试。我在属性周围添加了引号,并在字符串中引用了引号。 你现在的做法,你可能会得到太多的引用..不确定是否必须在 JSON "blah ' blah" 字符串中引用 ' ? :) @Jaanus -- 可能是对的,只需要引用双引号。不过我不认为它会受到伤害。 @tv - 我检查了 JSON 标准和 Doug Crockford 的 JSON stringifier。 JSON 标准明确讨论了双引号,因此双引号是唯一需要在字符串中转义的引号,而不是单引号。会很痛,因为输出中会有额外的反斜杠字符。【参考方案3】:

以下源代码是我的解决方案。我认为已经足够清楚地展示了将ul转换为json对象的原理。祝你好运:)

$(function() 

  function buildJSON($li) 
    var subObj =  "name": $li.contents().eq(0).text().trim() ;
    $li.children('ul').children().each(function() 
      if (!subObj.children)  subObj.children = []; 
      subObj.children.push(buildJSON($(this)));
    );
    return subObj;
  
    
  var obj = buildJSON($("#ul-data").children());
  $('body').append('<pre>').find('pre').append(JSON.stringify(obj, null, 2));

);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="ul-data">
  <li><a href="#">AAA</a>
    <ul>
      <li><a href="#">DDD</a>
        <ul>
          <li><a href="#">EEE</a>
            <ul>
              <li><a href="#">FFF</a></li>
            </ul>
          </li>
        </ul>
      </li>
      <li><a href="#">BBB</a></li>
      <li><a href="#">CCC</a></li>
    </ul>
  </li>
</ul>

【讨论】:

以上是关于jQuery 树遍历 - 将无序列表元素嵌套到 JSON的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法只为嵌套无序列表的父元素设置样式? [复制]

jQuery - live() 不能与附加 div 中的 next() 一起使用

如何垂直对齐嵌套在无序列表中的锚元素内的文本

急! jquery $.each 嵌套循环遍历

jQuery 遍历 - 祖先:向上遍历 DOM 树,以查找元素的祖先

如何根据每个无序列表中的列表项的数量在 Jquery 中隐藏按钮元素