Can I have a recursive JavaScript function inside the $ .getJSON function?

I have a variable depth JSON document. Example:

[ { "type": "firsttype", "text": { "id": "content" } } ] 

What I'm trying to do is get the values ​​of certain keys, for example text . Since I do not know where these keys can appear in .JSON, I need to use a recursive function. Then I try to display these keys and values ​​in an HTML file.

I have a preliminary attempt:

 $.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" ); }); 

When I load a page locally or remotely or on python -m SimpleHTTPServer , I get no errors and nothing on the page. What am I doing wrong? I have included all JS in the $.getJSON call so that there are no problems with asynchronism.

In the future, I would also like to include regular expression checking so that I can retrieve values ​​with a specific string, for example. /http/ . What would be the best way to do this?

+5
source share
4 answers

As the other answers cover most of the things you should consider, I think I’ll just post a solution to your real problem. :)

You want to go through arbitrary JSON and search for a specific key and, possibly, a condition on its value. Then you want to return all the values ​​for the specified key (which pass your condition, if specified).

You have the following 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] } 

This snippet will look for the above json for some_key1 so that its value some_key1 with 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'); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
+1
source

I think your mistake is to declare variable references: it should be outside the recursive function that I think of. inside the function, it will be reinitialized every time.

 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" ); }); 
0
source

Try moving your function definition outside of the event handler:

  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); }); 

Feel free to edit this if there are errors.

The goal is to pass an array of references to a recursive function and prevent the function name from being mixed with getJSON, for clarity, at least, and so that you can pass an initialized sKey.

0
source

You can, but in your case you probably shouldn't

You can pass a named function as a callback function, which is useful for recursion (see Using Named Callback Functions in Javascript , Ben Put Methods ), but in your case you probably shouldn't.

Based on your example, there are some things you want to do before and after calling the recursive function. These things, such as declaring variables and adding elements to the body, will have to happen [once] outside of recursion.

So, pass the anonymous function as your callback containing the definition of the recursive function and calling it if necessary.

In your case, you want to call it for each object returned in the JSON response array. That way you can put it in an iterator. Here I used jQuery $.each() for convenience.

 /* FUNCTION THAT MAKES JSON REQUEST */ function doJsonThing() { /* BEGIN REWRITE OF OP 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 */ 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
0
source

Source: https://habr.com/ru/post/1232797/


All Articles