递归JSON生成函数
Recursive JSON Generation Function
这会有点啰嗦,但这里是:
我正在编写两个单独的 Web 应用程序:一个用于生成带有大量数据和格式信息的 JSON 对象,另一个用于将 JSON 对象转换为格式良好的 HTML 页面进行查看。我目前遇到的特定问题是嵌套列表。
对于查看应用程序,我编写了一个递归函数,它将解析提供的 javascript 对象并为具有任意大小的嵌套元素的列表创建 HTML。
function createUnorderedList(object) {
var ul = $('<ol>');
for (var i = 0; i < object.length; i++) {
if (object[i].children === undefined) {
ul.append($('<li>').text(object[i].value));
} else {
ul.append(
$('<li>').html(
object[i].value + "<ul>" + createUnorderedList(object[i].children) + "</ul>"));
}
}
return ul.html();
}
可以在此处查看该函数的 jsfiddle:jsfiddle: Recursive HTML List Generation
现在,我需要为事物的 JSON 创建端创建一个函数。在尝试并未能全神贯注于如何递归执行此操作后,我决定使用一个更线性的函数,参见此处:
function createList( array ) {
var json = { "value": [] } ;
var k = 0 ;
if(array[array.length-1] === "") array.pop() ;
for(var i=0; i<array.length; i++ ){
json.value.push( { "value": array[i] } ) ;
for(var j=i+1; j<array.length; j++) {
if(array[j].charAt(0) === '\t') {
array[j] = array[j].replace( /\t/, '' ) ;
i++;
if(json.value[k].children === undefined)
$.extend( json.value[k], { children : [] } ) ;
json.value[k].children.push( { "value": array[j] } ) ;
} else { k++; j=array.length; }
}
}
return json ;
}
jsfiddle: JSON List Generation.
这个函数只能处理一个数量级的嵌套列表,目前应该足够了,但并不理想。我怎样才能使这个函数能够生成具有任意大小的嵌套元素的 json 对象?
谢谢。
经过深思熟虑,我找到了解决方案。
首先,我更改了您的代码,为每个值创建一个 <li>
。 children是<li>
后的<ul>
.
function createUnorderedList(object) {
var ul = $('<ul>');
for (var i = 0; i < object.length; i++) {
ul.append($('<li>').text(object[i].value));
if (object[i].children) {
ul.append($('<ul>').html(createUnorderedList(object[i].children)));
}
}
return ul.html();
}
然后我创建了一个递归搜索所有元素的函数。 <ul>
是它前面 <li>
的 child。
var createJSONRecursive = function(elem, arr) {
var childNodes = elem.childNodes;
var nodeTmp;
for (var i = 0; i<childNodes.length; i++) {
var node = {};
var tagName = childNodes[i].tagName;
if (tagName == 'LI') {
node.value = childNodes[i].innerHTML;
if (i < childNodes.length - 1 && childNodes[i+1].tagName == 'UL') {
nodeTmp = node;
}
else {
arr.push(node);
}
}
else if (tagName == 'UL') {
nodeTmp.children = [];
createJSONRecursive(childNodes[i], nodeTmp.children);
arr.push(nodeTmp);
}
}
}
var createJSON = function(elem) {
var json = {value:[]}
createJSONRecursive(elem, json.value);
return json;
}
var json = createJSON(document.getElementById('div'));
这里是fiddle:https://jsfiddle.net/8qc2mcyz/2/
编辑::起初我误解了你的问题。
这是将 ul
层次结构解析为对象的方法(查看 JS 控制台以查看解析出的内容):
function itemsToHierarchy(node) {
return $(node).find('> ul > li').toArray().map(function (item) {
return {
value: item.childNodes[0].textContent,
children: itemsToHierarchy(item)
};
});
}
console.log(itemsToHierarchy($('#list')));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<!-- leaving the HTML scrunched up to save space -->
<div id="list"><ul><li>Item 1<ul><li>Item 1.1</li></ul></li><li>Item 2</li><li>Item 3<ul><li>Item 3.1</li><li>Item 3.2<ul><li>Item 3.2.1<ul><li>Item 3.2.1.1</li></ul></li></ul></li></ul></li><li>Item 4<ul><li>Item 4.1</li><li>Item 4.2</li></ul></li><li>Item 5<ul><li>Item 5.1</li></ul></li></ul></div>
起初我以为您是在寻求有关 createList()
功能的帮助。这是适用于任何嵌套深度的递归版本:
function getItems( array, depth ) {
depth = depth || 0;
var items = [],
item = array.shift();
while (item && countTabs(item) === depth) {
items.push({
value: item.replace(/^\t*/, ''),
children: getItems(array, depth + 1)
});
item = array.shift();
}
if (item) { // not at this depth
array.unshift(item);
}
return items;
}
function countTabs(value) {
return value.match(/^\t*/)[0].length;
}
从中返回的值可用于构建 HTML,如下所示:
function createUnorderedList(items) {
return $('<ul>').append($.map(items, function (item) {
var li = $('<li>').text(item.value);
if (item.children.length) {
li.append(createUnorderedList(item.children));
}
return li;
}));
}
这会有点啰嗦,但这里是:
我正在编写两个单独的 Web 应用程序:一个用于生成带有大量数据和格式信息的 JSON 对象,另一个用于将 JSON 对象转换为格式良好的 HTML 页面进行查看。我目前遇到的特定问题是嵌套列表。
对于查看应用程序,我编写了一个递归函数,它将解析提供的 javascript 对象并为具有任意大小的嵌套元素的列表创建 HTML。
function createUnorderedList(object) {
var ul = $('<ol>');
for (var i = 0; i < object.length; i++) {
if (object[i].children === undefined) {
ul.append($('<li>').text(object[i].value));
} else {
ul.append(
$('<li>').html(
object[i].value + "<ul>" + createUnorderedList(object[i].children) + "</ul>"));
}
}
return ul.html();
}
可以在此处查看该函数的 jsfiddle:jsfiddle: Recursive HTML List Generation
现在,我需要为事物的 JSON 创建端创建一个函数。在尝试并未能全神贯注于如何递归执行此操作后,我决定使用一个更线性的函数,参见此处:
function createList( array ) {
var json = { "value": [] } ;
var k = 0 ;
if(array[array.length-1] === "") array.pop() ;
for(var i=0; i<array.length; i++ ){
json.value.push( { "value": array[i] } ) ;
for(var j=i+1; j<array.length; j++) {
if(array[j].charAt(0) === '\t') {
array[j] = array[j].replace( /\t/, '' ) ;
i++;
if(json.value[k].children === undefined)
$.extend( json.value[k], { children : [] } ) ;
json.value[k].children.push( { "value": array[j] } ) ;
} else { k++; j=array.length; }
}
}
return json ;
}
jsfiddle: JSON List Generation.
这个函数只能处理一个数量级的嵌套列表,目前应该足够了,但并不理想。我怎样才能使这个函数能够生成具有任意大小的嵌套元素的 json 对象?
谢谢。
经过深思熟虑,我找到了解决方案。
首先,我更改了您的代码,为每个值创建一个 <li>
。 children是<li>
后的<ul>
.
function createUnorderedList(object) {
var ul = $('<ul>');
for (var i = 0; i < object.length; i++) {
ul.append($('<li>').text(object[i].value));
if (object[i].children) {
ul.append($('<ul>').html(createUnorderedList(object[i].children)));
}
}
return ul.html();
}
然后我创建了一个递归搜索所有元素的函数。 <ul>
是它前面 <li>
的 child。
var createJSONRecursive = function(elem, arr) {
var childNodes = elem.childNodes;
var nodeTmp;
for (var i = 0; i<childNodes.length; i++) {
var node = {};
var tagName = childNodes[i].tagName;
if (tagName == 'LI') {
node.value = childNodes[i].innerHTML;
if (i < childNodes.length - 1 && childNodes[i+1].tagName == 'UL') {
nodeTmp = node;
}
else {
arr.push(node);
}
}
else if (tagName == 'UL') {
nodeTmp.children = [];
createJSONRecursive(childNodes[i], nodeTmp.children);
arr.push(nodeTmp);
}
}
}
var createJSON = function(elem) {
var json = {value:[]}
createJSONRecursive(elem, json.value);
return json;
}
var json = createJSON(document.getElementById('div'));
这里是fiddle:https://jsfiddle.net/8qc2mcyz/2/
编辑::起初我误解了你的问题。
这是将 ul
层次结构解析为对象的方法(查看 JS 控制台以查看解析出的内容):
function itemsToHierarchy(node) {
return $(node).find('> ul > li').toArray().map(function (item) {
return {
value: item.childNodes[0].textContent,
children: itemsToHierarchy(item)
};
});
}
console.log(itemsToHierarchy($('#list')));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<!-- leaving the HTML scrunched up to save space -->
<div id="list"><ul><li>Item 1<ul><li>Item 1.1</li></ul></li><li>Item 2</li><li>Item 3<ul><li>Item 3.1</li><li>Item 3.2<ul><li>Item 3.2.1<ul><li>Item 3.2.1.1</li></ul></li></ul></li></ul></li><li>Item 4<ul><li>Item 4.1</li><li>Item 4.2</li></ul></li><li>Item 5<ul><li>Item 5.1</li></ul></li></ul></div>
起初我以为您是在寻求有关 createList()
功能的帮助。这是适用于任何嵌套深度的递归版本:
function getItems( array, depth ) {
depth = depth || 0;
var items = [],
item = array.shift();
while (item && countTabs(item) === depth) {
items.push({
value: item.replace(/^\t*/, ''),
children: getItems(array, depth + 1)
});
item = array.shift();
}
if (item) { // not at this depth
array.unshift(item);
}
return items;
}
function countTabs(value) {
return value.match(/^\t*/)[0].length;
}
从中返回的值可用于构建 HTML,如下所示:
function createUnorderedList(items) {
return $('<ul>').append($.map(items, function (item) {
var li = $('<li>').text(item.value);
if (item.children.length) {
li.append(createUnorderedList(item.children));
}
return li;
}));
}