我有一个可变深度的JSON文档。一个例子:
[
{
"type": "firsttype",
"text": {
"id": "content"
}
}
]
我要做的是检索某些键的值,比如说text
。由于我不知道这些密钥在.JSON中可能出现在哪里,我需要使用递归函数。然后我尝试在HTML文件中显示这些键和值。
我在这里有一个初步尝试:
$.getJSON("file.json", function getText (oValue, sKey) {
links = [];
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (oValue [i], i);
}
} else {
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
});
当我在本地或远程或python -m SimpleHTTPServer
加载页面时,我没有错误,页面上没有任何内容。我究竟做错了什么?我在$.getJSON
调用中包含了所有JS,因此不会出现异步问题。
将来我还希望包含一个regexp检查,以便我可以使用某个字符串提取值,例如/http/
。最好的方法是什么?
答案 0 :(得分:1)
由于其他答案涵盖了您应该考虑的大部分事项,我想我会为您的实际问题发布一个解决方案。 :)
您希望遍历任意JSON并搜索特定键,并且可能对其值有条件。然后,您希望返回指定键的所有值(如果指定,则传递您的条件)。
考虑一下你有以下json:
{
"hello": "some text",
"object": {
"key1": "hello!",
"key2": "Bye!"
},
"array": [{
"some_key1": "blah blah blah",
"some_key2": 24
}, {
"some_key1": "ghiojd",
"some_key2": 13
}],
"numeric_array": [2, 3, 4, 5]
}
此代码段会在上面的json中搜索some_key1
,其值以blah
开头:
function regexpConditionFactory(regex) {
return function(value) { return regex.test(value); };
}
function searchObjectForKey(obj, key, condition, result) {
if ($.isPlainObject(obj)) {
if (obj.hasOwnProperty(key)) {
if (!condition || ($.isFunction(condition) && condition(obj[key])))
result.push(obj[key]);
}
}
if ($.isPlainObject(obj) || $.isArray(obj)) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
searchObjectForKey(obj[k], key, condition, result);
}
}
}
$.getJSON('file.json', function(data) {
var res = [];
searchObjectForKey(data, 'some_key1', regexpConditionFactory(/^blah/), res);
$('<ul/>', {
'class': 'my-new-list',
'html': res.map(function(value) { return '<li>' + value + '</li>'; }).join('')
}).appendTo('body');
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
答案 1 :(得分:0)
我认为您的错误在于变量链接的声明: 它必须在我认为的递归函数之外。 在函数内部,它每次都会重新初始化。
var links = [];
$.getJSON("file.json", function getText (oValue, sKey) {
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (oValue [i], i);
}
} else {
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
});
答案 2 :(得分:0)
尝试在事件处理程序之外移动函数定义:
function getText (links, oValue, sKey) {
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (links, oValue [i], i);
}
} else {
if(oValue && sKey)
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
};
$.getJSON("file.json", function(data, success){
var links = [];
getText (links, data, 0);
});
如果有错误,请随意编辑。
目的是将链接数组传递给递归函数,并避免将命名函数定义与getJSON混合,至少要清楚,并确保您可以传递初始化的sKey。
答案 3 :(得分:0)
你可以传递一个命名函数作为回调函数 - 这对于递归很有用(参见:Using Named Callback Functions In Javascript Methods,Ben Nadel) - 但在你的情况下,你可能不应该。
根据您的示例,在调用递归函数之前和之后,您需要执行一些操作。这些事情,例如声明变量和向主体附加元素,需要在递归之外[一次]发生。
因此,传递一个匿名函数作为包含递归函数定义的回调函数,并根据需要调用它。
在您的情况下,您将要为JSON响应数组中返回的每个对象调用它。所以,你也可以把它放在迭代器里面。为方便起见,我在这里使用了jQuery&#39; $.each()
。
/* FUNCTION THAT MAKES JSON REQUEST */
function doJsonThing() {
/* BEGIN REWRITE OF OP's EXAMPLE CODE */
$.getJSON('file.json', function (json) {
var links = [];
function getText (key, val) {
if (typeof val === 'object' || typeof val === 'array') {
for (i in val) {
getText(i, val[i]);
}
} else {
links.push('<li id="' + val + '">' + key + ' (' + val + ')</li>' );
}
}
$.each(json, function (key, val) {
getText(key, val);
});
$('<ul/>', {
"class": "my-new-list",
"html" : links.join('')
}).appendTo('body');
});
/* END REWRITE OF EXAMPLE CODE */
}
/* THE FOLLOWING IS NOT PART OF THE EXAMPLE,
// IT IS JUST USED TO SIMULATE A SERVER RESPONSE */
/* BEGIN UNIT TEST */
// CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
function json_response(response) {
return function (url, success) {
success(response);
};
}
// OVERRIDE $.getJSON WITH DUMMY FUNCTION AND FAKE RESPONSE
$.getJSON = json_response(
// SIMULATED CONTENTS OF 'file.json'
$.parseJSON(
'['
+ ' {'
+ ' "type": "firsttype",'
+ ' "text": {'
+ ' "id": "content"'
+ ' }'
+ ' },'
+ ' {'
+ ' "type": "secondtype",'
+ ' "text": {'
+ ' "id": "other"'
+ ' }'
+ ' }'
+ ']'
)
);
doJsonThing();
/* END UNIT TEST */
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;