嵌套 JSON 迭代,超出最大调用堆栈大小
Nested JSON iterate, Maximum call stack size exceeded
我已经实现了一个递归函数来遍历嵌套 JSON。我面临的问题是它抛出错误
Maximum call stack exceeded
我实现的功能如下,
function createTreeMap (treeCatalog){
var _this = this;
_.each(treeCatalog, function (ele, inx){
if(typeof (ele) === "object"){
createTreeMap(ele);
}else{
//I create another JSON structure with the value as its property and its value as 1.
_this.treeMap[ele] = 1;
}
});
}
我正在遍历的 JSON 看起来像这样,
[{
"EmployeeID": 2,
"FirstName": "Andrew",
"LastName": "Fuller",
"Country": "USA",
"Title": "Vice President, Sales",
"HireDate": "1992-08-14 00:00:00",
"BirthDate": "1952-02-19 00:00:00",
"City": "Tacoma",
"Address": "908 W. Capital Way",
children: [{
"EmployeeID": 8,
"FirstName": "Laura",
"LastName": "Callahan",
"Country": "USA",
"Title": "Inside Sales Coordinator",
"HireDate": "1994-03-05 00:00:00",
"BirthDate": "1958-01-09 00:00:00",
"City": "Seattle",
"Address": "4726 - 11th Ave. N.E."
}, {
"EmployeeID": 1,
"FirstName": "Nancy",
"LastName": "Davolio",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-05-01 00:00:00",
"BirthDate": "1948-12-08 00:00:00",
"City": "Seattle",
"Address": "507 - 20th Ave. E.Apt. 2A"
}, {
"EmployeeID": 3,
"FirstName": "Janet",
"LastName": "Leverling",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-04-01 00:00:00",
"BirthDate": "1963-08-30 00:00:00",
"City": "Kirkland",
"Address": "722 Moss Bay Blvd."
}, {
"EmployeeID": 4,
"FirstName": "Margaret",
"LastName": "Peacock",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1993-05-03 00:00:00",
"BirthDate": "1937-09-19 00:00:00",
"City": "Redmond",
"Address": "4110 Old Redmond Rd."
}, {
"EmployeeID": 5,
"FirstName": "Steven",
"LastName": "Buchanan",
"Country": "UK",
"Title": "Sales Manager",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1955-03-04 00:00:00",
"City": "London",
"Address": "14 Garrett Hill",
"expanded": "true",
children: [{
"EmployeeID": 6,
"FirstName": "Michael",
"LastName": "Suyama",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1963-07-02 00:00:00",
"City": "London",
"Address": "Coventry House Miner Rd."
}, {
"EmployeeID": 7,
"FirstName": "Robert",
"LastName": "King",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-01-02 00:00:00",
"BirthDate": "1960-05-29 00:00:00",
"City": "London",
"Address": "Edgeham Hollow Winchester Way"
},{
"EmployeeID": 9,
"FirstName": "Anne",
"LastName": "Dodsworth",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-11-15 00:00:00",
"BirthDate": "1966-01-27 00:00:00",
"City": "London",
"Address": "7 Houndstooth Rd."
}]
}]
}];
我怀疑是相似的 child 属性 名字。但是有没有合适的方法来解决这个问题,因为相似的 child 名称是必需的。
非常感谢:)
更新
这个例子模拟了我遇到的问题:http://jsfiddle.net/qaoapays/1/
Hasitha,我认为您正在将正在编目的对象 ("ele") 放回函数本身。
而不是
createTreeMap(ele);
尝试这样的事情
createTreeMap(ele.child);
将您的源代码绑定到 jqxTreeGrid
后,对它的结构做了一个小改动:添加 parent 属性 和 data 属性,其中 data - 对 self.
的引用
作为解决方法,为了避免无限递归,您需要错过这个 属性,类似于
function iterate (obj){
_.each(obj, function(ele, inx){
if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
iterate(ele);
}else{
console.log(ele);
}
});
}
var employees =
[{
"EmployeeID": 2,
"FirstName": "Andrew",
"LastName": "Fuller",
"Country": "USA",
"Title": "Vice President, Sales",
"HireDate": "1992-08-14 00:00:00",
"BirthDate": "1952-02-19 00:00:00",
"City": "Tacoma",
"Address": "908 W. Capital Way",
children: [{
"EmployeeID": 8,
"FirstName": "Laura",
"LastName": "Callahan",
"Country": "USA",
"Title": "Inside Sales Coordinator",
"HireDate": "1994-03-05 00:00:00",
"BirthDate": "1958-01-09 00:00:00",
"City": "Seattle",
"Address": "4726 - 11th Ave. N.E."
}, {
"EmployeeID": 1,
"FirstName": "Nancy",
"LastName": "Davolio",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-05-01 00:00:00",
"BirthDate": "1948-12-08 00:00:00",
"City": "Seattle",
"Address": "507 - 20th Ave. E.Apt. 2A"
}, {
"EmployeeID": 3,
"FirstName": "Janet",
"LastName": "Leverling",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-04-01 00:00:00",
"BirthDate": "1963-08-30 00:00:00",
"City": "Kirkland",
"Address": "722 Moss Bay Blvd."
}, {
"EmployeeID": 4,
"FirstName": "Margaret",
"LastName": "Peacock",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1993-05-03 00:00:00",
"BirthDate": "1937-09-19 00:00:00",
"City": "Redmond",
"Address": "4110 Old Redmond Rd."
}, {
"EmployeeID": 5,
"FirstName": "Steven",
"LastName": "Buchanan",
"Country": "UK",
"Title": "Sales Manager",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1955-03-04 00:00:00",
"City": "London",
"Address": "14 Garrett Hill",
"expanded": "true",
children: [{
"EmployeeID": 6,
"FirstName": "Michael",
"LastName": "Suyama",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1963-07-02 00:00:00",
"City": "London",
"Address": "Coventry House Miner Rd."
}, {
"EmployeeID": 7,
"FirstName": "Robert",
"LastName": "King",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-01-02 00:00:00",
"BirthDate": "1960-05-29 00:00:00",
"City": "London",
"Address": "Edgeham Hollow Winchester Way"
}, {
"EmployeeID": 9,
"FirstName": "Anne",
"LastName": "Dodsworth",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-11-15 00:00:00",
"BirthDate": "1966-01-27 00:00:00",
"City": "London",
"Address": "7 Houndstooth Rd."
}]
}]
}];
//// prepare the data
var source = {
dataType: "json",
dataFields: [{
name: 'EmployeeID',
type: 'number'
}, {
name: 'FirstName',
type: 'string'
}, {
name: 'LastName',
type: 'string'
}, {
name: 'Country',
type: 'string'
}, {
name: 'City',
type: 'string'
}, {
name: 'Address',
type: 'string'
}, {
name: 'Title',
type: 'string'
}, {
name: 'HireDate',
type: 'date'
}, {
name: 'children',
type: 'array'
}, {
name: 'expanded',
type: 'bool'
}, {
name: 'BirthDate',
type: 'date'
}],
hierarchy: {
root: 'children'
},
id: 'EmployeeID',
localData: employees
};
var dataAdapter = new $.jqx.dataAdapter(source);
// create Tree Grid
$("#treeGrid").jqxTreeGrid({
width: 680,
source: dataAdapter,
editable: true,
filterable: true,
theme: 'energyblue',
columns: [{
text: 'FirstName',
dataField: 'FirstName',
width: 150
}, {
text: 'LastName',
dataField: 'LastName',
width: 120
}, {
text: 'Title',
dataField: 'Title',
width: 200
}, {
text: 'Birth Date',
dataField: 'BirthDate',
cellsFormat: 'd',
width: 120
}, {
text: 'Hire Date',
dataField: 'HireDate',
cellsFormat: 'd',
width: 120
}, {
text: 'Address',
dataField: 'Address',
width: 250
}, {
text: 'City',
dataField: 'City',
width: 120
}, {
text: 'Country',
dataField: 'Country',
width: 120
}]
});
$("#jqxbutton").jqxButton({
theme: 'energyblue',
height: 30
});
$('#jqxbutton').click(function () {
$("#treeGrid").jqxTreeGrid('expandRow',2);
iterate(employees);
});
function iterate (obj){
_.each(obj, function(ele, inx){
if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
iterate(ele);
}else{
console.log(ele);
}
});
}
<script src="http://documentcloud.github.io/underscore/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.energyblue.css" rel="stylesheet"/>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css" rel="stylesheet"/>
<script src="http://jqwidgets.com/public/jqwidgets/jqx-all.js"></script>
<div id="treeGrid"></div>
<input type="button" style="margin: 20px;" id="jqxbutton" value="Expand a row" />
另一种方式:传递给源 - 深度克隆对象
我已经实现了一个递归函数来遍历嵌套 JSON。我面临的问题是它抛出错误
Maximum call stack exceeded
我实现的功能如下,
function createTreeMap (treeCatalog){
var _this = this;
_.each(treeCatalog, function (ele, inx){
if(typeof (ele) === "object"){
createTreeMap(ele);
}else{
//I create another JSON structure with the value as its property and its value as 1.
_this.treeMap[ele] = 1;
}
});
}
我正在遍历的 JSON 看起来像这样,
[{
"EmployeeID": 2,
"FirstName": "Andrew",
"LastName": "Fuller",
"Country": "USA",
"Title": "Vice President, Sales",
"HireDate": "1992-08-14 00:00:00",
"BirthDate": "1952-02-19 00:00:00",
"City": "Tacoma",
"Address": "908 W. Capital Way",
children: [{
"EmployeeID": 8,
"FirstName": "Laura",
"LastName": "Callahan",
"Country": "USA",
"Title": "Inside Sales Coordinator",
"HireDate": "1994-03-05 00:00:00",
"BirthDate": "1958-01-09 00:00:00",
"City": "Seattle",
"Address": "4726 - 11th Ave. N.E."
}, {
"EmployeeID": 1,
"FirstName": "Nancy",
"LastName": "Davolio",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-05-01 00:00:00",
"BirthDate": "1948-12-08 00:00:00",
"City": "Seattle",
"Address": "507 - 20th Ave. E.Apt. 2A"
}, {
"EmployeeID": 3,
"FirstName": "Janet",
"LastName": "Leverling",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-04-01 00:00:00",
"BirthDate": "1963-08-30 00:00:00",
"City": "Kirkland",
"Address": "722 Moss Bay Blvd."
}, {
"EmployeeID": 4,
"FirstName": "Margaret",
"LastName": "Peacock",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1993-05-03 00:00:00",
"BirthDate": "1937-09-19 00:00:00",
"City": "Redmond",
"Address": "4110 Old Redmond Rd."
}, {
"EmployeeID": 5,
"FirstName": "Steven",
"LastName": "Buchanan",
"Country": "UK",
"Title": "Sales Manager",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1955-03-04 00:00:00",
"City": "London",
"Address": "14 Garrett Hill",
"expanded": "true",
children: [{
"EmployeeID": 6,
"FirstName": "Michael",
"LastName": "Suyama",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1963-07-02 00:00:00",
"City": "London",
"Address": "Coventry House Miner Rd."
}, {
"EmployeeID": 7,
"FirstName": "Robert",
"LastName": "King",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-01-02 00:00:00",
"BirthDate": "1960-05-29 00:00:00",
"City": "London",
"Address": "Edgeham Hollow Winchester Way"
},{
"EmployeeID": 9,
"FirstName": "Anne",
"LastName": "Dodsworth",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-11-15 00:00:00",
"BirthDate": "1966-01-27 00:00:00",
"City": "London",
"Address": "7 Houndstooth Rd."
}]
}]
}];
我怀疑是相似的 child 属性 名字。但是有没有合适的方法来解决这个问题,因为相似的 child 名称是必需的。
非常感谢:)
更新
这个例子模拟了我遇到的问题:http://jsfiddle.net/qaoapays/1/
Hasitha,我认为您正在将正在编目的对象 ("ele") 放回函数本身。
而不是
createTreeMap(ele);
尝试这样的事情
createTreeMap(ele.child);
将您的源代码绑定到 jqxTreeGrid
后,对它的结构做了一个小改动:添加 parent 属性 和 data 属性,其中 data - 对 self.
的引用
作为解决方法,为了避免无限递归,您需要错过这个 属性,类似于
function iterate (obj){
_.each(obj, function(ele, inx){
if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
iterate(ele);
}else{
console.log(ele);
}
});
}
var employees =
[{
"EmployeeID": 2,
"FirstName": "Andrew",
"LastName": "Fuller",
"Country": "USA",
"Title": "Vice President, Sales",
"HireDate": "1992-08-14 00:00:00",
"BirthDate": "1952-02-19 00:00:00",
"City": "Tacoma",
"Address": "908 W. Capital Way",
children: [{
"EmployeeID": 8,
"FirstName": "Laura",
"LastName": "Callahan",
"Country": "USA",
"Title": "Inside Sales Coordinator",
"HireDate": "1994-03-05 00:00:00",
"BirthDate": "1958-01-09 00:00:00",
"City": "Seattle",
"Address": "4726 - 11th Ave. N.E."
}, {
"EmployeeID": 1,
"FirstName": "Nancy",
"LastName": "Davolio",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-05-01 00:00:00",
"BirthDate": "1948-12-08 00:00:00",
"City": "Seattle",
"Address": "507 - 20th Ave. E.Apt. 2A"
}, {
"EmployeeID": 3,
"FirstName": "Janet",
"LastName": "Leverling",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1992-04-01 00:00:00",
"BirthDate": "1963-08-30 00:00:00",
"City": "Kirkland",
"Address": "722 Moss Bay Blvd."
}, {
"EmployeeID": 4,
"FirstName": "Margaret",
"LastName": "Peacock",
"Country": "USA",
"Title": "Sales Representative",
"HireDate": "1993-05-03 00:00:00",
"BirthDate": "1937-09-19 00:00:00",
"City": "Redmond",
"Address": "4110 Old Redmond Rd."
}, {
"EmployeeID": 5,
"FirstName": "Steven",
"LastName": "Buchanan",
"Country": "UK",
"Title": "Sales Manager",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1955-03-04 00:00:00",
"City": "London",
"Address": "14 Garrett Hill",
"expanded": "true",
children: [{
"EmployeeID": 6,
"FirstName": "Michael",
"LastName": "Suyama",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1993-10-17 00:00:00",
"BirthDate": "1963-07-02 00:00:00",
"City": "London",
"Address": "Coventry House Miner Rd."
}, {
"EmployeeID": 7,
"FirstName": "Robert",
"LastName": "King",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-01-02 00:00:00",
"BirthDate": "1960-05-29 00:00:00",
"City": "London",
"Address": "Edgeham Hollow Winchester Way"
}, {
"EmployeeID": 9,
"FirstName": "Anne",
"LastName": "Dodsworth",
"Country": "UK",
"Title": "Sales Representative",
"HireDate": "1994-11-15 00:00:00",
"BirthDate": "1966-01-27 00:00:00",
"City": "London",
"Address": "7 Houndstooth Rd."
}]
}]
}];
//// prepare the data
var source = {
dataType: "json",
dataFields: [{
name: 'EmployeeID',
type: 'number'
}, {
name: 'FirstName',
type: 'string'
}, {
name: 'LastName',
type: 'string'
}, {
name: 'Country',
type: 'string'
}, {
name: 'City',
type: 'string'
}, {
name: 'Address',
type: 'string'
}, {
name: 'Title',
type: 'string'
}, {
name: 'HireDate',
type: 'date'
}, {
name: 'children',
type: 'array'
}, {
name: 'expanded',
type: 'bool'
}, {
name: 'BirthDate',
type: 'date'
}],
hierarchy: {
root: 'children'
},
id: 'EmployeeID',
localData: employees
};
var dataAdapter = new $.jqx.dataAdapter(source);
// create Tree Grid
$("#treeGrid").jqxTreeGrid({
width: 680,
source: dataAdapter,
editable: true,
filterable: true,
theme: 'energyblue',
columns: [{
text: 'FirstName',
dataField: 'FirstName',
width: 150
}, {
text: 'LastName',
dataField: 'LastName',
width: 120
}, {
text: 'Title',
dataField: 'Title',
width: 200
}, {
text: 'Birth Date',
dataField: 'BirthDate',
cellsFormat: 'd',
width: 120
}, {
text: 'Hire Date',
dataField: 'HireDate',
cellsFormat: 'd',
width: 120
}, {
text: 'Address',
dataField: 'Address',
width: 250
}, {
text: 'City',
dataField: 'City',
width: 120
}, {
text: 'Country',
dataField: 'Country',
width: 120
}]
});
$("#jqxbutton").jqxButton({
theme: 'energyblue',
height: 30
});
$('#jqxbutton').click(function () {
$("#treeGrid").jqxTreeGrid('expandRow',2);
iterate(employees);
});
function iterate (obj){
_.each(obj, function(ele, inx){
if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
iterate(ele);
}else{
console.log(ele);
}
});
}
<script src="http://documentcloud.github.io/underscore/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.energyblue.css" rel="stylesheet"/>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css" rel="stylesheet"/>
<script src="http://jqwidgets.com/public/jqwidgets/jqx-all.js"></script>
<div id="treeGrid"></div>
<input type="button" style="margin: 20px;" id="jqxbutton" value="Expand a row" />
另一种方式:传递给源 - 深度克隆对象