将嵌套列表转换为嵌套对象?

时间:2017-03-27 14:13:32

标签: javascript jquery

以下几乎可以正常工作,但如果我删除<a> json中断了一个空节点name:" ",而且我相信我正在创建一个数组,而我需要下面格式的json。这里也是jsFiddle(参见下面我正在寻找的输出的结果)。

我要做的是生成一个我可以从嵌套列表中读取的对象,以生成思维导图(D3)like this

HTML

<div id="tree">
<ul class="sortable">
  <li><a href="http://google.com">flare</a>
    <ul class="sortable">
      <li>analytics
        <ul class="sortable">
          <li><a href="http://google.com">cluster</a>
            <ul class="sortable">
              <li><a href="http://google.com">AgglomerativeCluster</a></li>
              <li><a href="http://google.com">CommunityStructure</a></li>
              <li><a href="http://google.com">HierarchicalCluster</a></li>
              <li><a href="http://google.com">MergeEdge</a></li>
            </ul>
          </li>
          <li><a href="http://google.com">graph</a>
            <ul class="sortable">
              <li><a href="http://google.com">BetweennessCentrality</a></li>
              <li><a href="http://google.com">LinkDistance</a></li>
              <li><a href="http://google.com">MaxFlowMinCut</a></li>
              <li><a href="http://google.com">ShortestPaths</a></li>
              <li><a href="http://google.com">SpanningTree</a></li>
            </ul>
          </li>
          <li><a href="http://google.com">optimization</a>
            <ul class="sortable">
              <li><a href="http://google.com">AspectRatioBanker</a></li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="http://google.com">Pippo</a></li>
  <li><a href="http://google.com">buonanotte</a></li>
  <li><a href="http://google.com">Avantieri</a></li>
</ul>
</div>
<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>


<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>
<div id="json_results" style="margin-top: 40px; padding-top: 20px;">
Needs to become:
  <pre style="padding-top: 20px;">
var root = JSON.parse( ' {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster","url":"http://google.com"},
      {"name": "CommunityStructure"},
      {"name": "HierarchicalCluster"},
      {"name": "MergeEdge"}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality" },
      {"name": "LinkDistance" },
      {"name": "MaxFlowMinCut" },
      {"name": "ShortestPaths" },
      {"name": "SpanningTree" }
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker" }
     ]
    }
   ]
  },
  {"name": "Pippo"},
  {"name": "buonanotte" },
  {"name": "Avantieri"}
 ]
} ') ;
  </pre>
</div>

JS

$(document).ready(function () {
    var out = [];
    function processOneLi(node) {       
        var aNode = node.children("a:first");
        var retVal = {
            "name": aNode.text(),
            "url": aNode.attr("href")
        };
        node.find("> .sortable > li").each(function() {
            if (!retVal.hasOwnProperty("children")) {
                retVal.children = [];
            }
            retVal.children.push(processOneLi($(this)));
        });
        return retVal;
    }
    $("#tree > ul > li").each(function() {
        out.push(processOneLi($(this)));
    });
    $('#d pre').text(JSON.stringify(out, null, 2));

});

json应该成为:

var root = JSON.parse( ' {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster","url":"http://google.com"},
      {"name": "CommunityStructure"},
      {"name": "HierarchicalCluster"},
      {"name": "MergeEdge"}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality" },
      {"name": "LinkDistance" },
      {"name": "MaxFlowMinCut" },
      {"name": "ShortestPaths" },
      {"name": "SpanningTree" }
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker" }
     ]
    }
   ]
  },
  {"name": "Pippo"},
  {"name": "buonanotte" },
  {"name": "Avantieri"}
 ]
} ') ;

但这就是我所得到的:

[
  {
    "name": "flare",
    "url": "http://google.com",
    "children": [
      {
        "name": "",
        "children": [
          {
            "name": "cluster",
            "url": "http://google.com",
            "children": [
              {
                "name": "AgglomerativeCluster",
                "url": "http://google.com"
              },
              {
                "name": "CommunityStructure",
                "url": "http://google.com"
              },
              {
                "name": "HierarchicalCluster",
                "url": "http://google.com"
              },
              {
                "name": "MergeEdge",
                "url": "http://google.com"
              }
            ]
          },
          {
            "name": "graph",
            "url": "http://google.com",
            "children": [
              {
                "name": "BetweennessCentrality",
                "url": "http://google.com"
              },
              {
                "name": "LinkDistance",
                "url": "http://google.com"
              },
              {
                "name": "MaxFlowMinCut",
                "url": "http://google.com"
              },
              {
                "name": "ShortestPaths",
                "url": "http://google.com"
              },
              {
                "name": "SpanningTree",
                "url": "http://google.com"
              }
            ]
          },
          {
            "name": "optimization",
            "url": "http://google.com",
            "children": [
              {
                "name": "AspectRatioBanker",
                "url": "http://google.com"
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "name": "Pippo",
    "url": "http://google.com"
  },
  {
    "name": "buonanotte",
    "url": "http://google.com"
  },
  {
    "name": "Avantieri",
    "url": "http://google.com"
  }
]

这是jsFiddle(见下面我要找的输出结果)

3 个答案:

答案 0 :(得分:1)

一个小的递归函数可以:

function listToObject(list) {
  return $(list).first().children("li").map(function () {
    var $this = $(this), $name = $this.children("a").first();
    return {
                            // see http://stackoverflow.com/a/8851526
      name: $name.text() || $this.clone().children().remove().end().text().trim(),
      url: $name.attr("href"),
      children: listToObject($this.children("ul"))
    };
  }).toArray();
}

var output = listToObject($("#tree > ul"));
console.log(output);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="tree">
  <ul class="sortable">
    <li><a href="http://google.com">flare</a>
      <ul class="sortable">
        <li>analytics
          <ul class="sortable">
            <li><a href="http://google.com">cluster</a>
              <ul class="sortable">
                <li><a href="http://google.com">AgglomerativeCluster</a></li>
                <li><a href="http://google.com">CommunityStructure</a></li>
                <li><a href="http://google.com">HierarchicalCluster</a></li>
                <li><a href="http://google.com">MergeEdge</a></li>
              </ul>
            </li>
            <li><a href="http://google.com">graph</a>
              <ul class="sortable">
                <li><a href="http://google.com">BetweennessCentrality</a></li>
                <li><a href="http://google.com">LinkDistance</a></li>
                <li><a href="http://google.com">MaxFlowMinCut</a></li>
                <li><a href="http://google.com">ShortestPaths</a></li>
                <li><a href="http://google.com">SpanningTree</a></li>
              </ul>
            </li>
            <li><a href="http://google.com">optimization</a>
              <ul class="sortable">
                <li><a href="http://google.com">AspectRatioBanker</a></li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="http://google.com">Pippo</a></li>
    <li><a href="http://google.com">buonanotte</a></li>
    <li><a href="http://google.com">Avantieri</a></li>
  </ul>
</div>

输出比你要求的要严格得多。每个对象都有一个urlchildren,即使是空的。这实际上最终会使处理变得更容易。

答案 1 :(得分:0)

我发现了你的问题,有一个li元素没有你想要的元素。

这将为您提供您正在寻找的结果

$(document).ready(function () {
    var out = [];
    function processOneLi(node) {
        var aNode = node.children("a:first");
        var retVal = {};
        if (aNode.text()) {
           retVal = {
              "name": aNode.text(),
              "url": aNode.attr("href")
           };
        } else {
          retVal = { "name": node.clone().children().remove().end().text().replace(/\r?\n|\r/g, " ") };
        }
        node.find("> .sortable > li").each(function() {
            if (!retVal.hasOwnProperty("children")) {
                retVal.children = [];
            }
            retVal.children.push(processOneLi($(this)));
        });
        return retVal;
    }
    $("#tree > ul > li").each(function() {
        out.push(processOneLi($(this)));
    });
    $('#d pre').text(JSON.stringify(out, null, 2));

});

答案 2 :(得分:0)

你的问题是Pippo,buonanotte和Avantieri是耀斑的兄弟姐妹,而不是在耀斑下嵌套。

我想我得到了你在这个小提琴中所期望的结果:http://jsfiddle.net/k7vSg/122/

<强> HTML:

<div id="tree">
<ul class="sortable">
  <li><a href="http://google.com">flare</a>
    <ul class="sortable">
      <li>analytics
        <ul class="sortable">
          <li><a href="http://google.com">cluster</a>
            <ul class="sortable">
              <li><a href="http://google.com">AgglomerativeCluster</a></li>
              <li><a href="http://google.com">CommunityStructure</a></li>
              <li><a href="http://google.com">HierarchicalCluster</a></li>
              <li><a href="http://google.com">MergeEdge</a></li>
            </ul>
          </li>
          <li><a href="http://google.com">graph</a>
            <ul class="sortable">
              <li><a href="http://google.com">BetweennessCentrality</a></li>
              <li><a href="http://google.com">LinkDistance</a></li>
              <li><a href="http://google.com">MaxFlowMinCut</a></li>
              <li><a href="http://google.com">ShortestPaths</a></li>
              <li><a href="http://google.com">SpanningTree</a></li>
            </ul>
          </li>
          <li><a href="http://google.com">optimization</a>
            <ul class="sortable">
              <li><a href="http://google.com">AspectRatioBanker</a></li>
            </ul>
          </li>
        </ul>
      </li>
      <li><a href="http://google.com">Pippo</a></li>
      <li><a href="http://google.com">buonanotte</a></li>
      <li><a href="http://google.com">Avantieri</a></li>
    </ul>
  </li>

</ul>
</div>



<div id="d" style="margin-top: 40px; padding-top: 20px;">Output:<br><br><pre></pre></div>
<div id="json_results" style="margin-top: 40px; padding-top: 20px;">
Needs to become:
  <pre style="padding-top: 20px;">
var root = JSON.parse( ' {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster","url":"http://google.com"},
      {"name": "CommunityStructure"},
      {"name": "HierarchicalCluster"},
      {"name": "MergeEdge"}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality" },
      {"name": "LinkDistance" },
      {"name": "MaxFlowMinCut" },
      {"name": "ShortestPaths" },
      {"name": "SpanningTree" }
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker" }
     ]
    }
   ]
  },
  {"name": "Pippo"},
  {"name": "buonanotte" },
  {"name": "Avantieri"}
 ]
} ') ;
  </pre>
</div>

<强> JS:

$(document).ready(function () {
    var out = [];
    function processOneLi(node) {       
        var aNode = node.children("a:first");
        var retVal = {
            "name": aNode.text(),
            "url": aNode.attr("href")
        };
        node.find("> .sortable > li").each(function() {
            if (!retVal.hasOwnProperty("children")) {
                retVal.children = [];
            }
            retVal.children.push(processOneLi($(this)));
        });
        return retVal;
    }
    $("#tree > ul > li").each(function() {
        out.push(processOneLi($(this)));
    });

    $('#d pre').text(JSON.stringify(out[0], null, 2));

});