tultalk has asked for the wisdom of the Perl Monks concerning the following question:

Hi

How do I capture the JSON data in a usable manner?

Thanks

Following code executes the CGI script:

<script type="text/javascript"> $(document).ready(function(){ alert("entered function"); $.getJSON("http://www.xxx.org/httpsdocs/cgi-bin/update_tables.cgi?ac +tion=updatetable_167&kind=0&searchterm=19", function(data){ $.each(data, function(key, value){ document.write(key+":"+value+"<br />"); }); }); }); </script

Nothing printed out

Below is log showing that the query was executed and returned the correct values

[Tue Mar 20 19:59:06 2018] update_tables.cgi: searchterm = '19' at upd +ate_tables.cgi line 439. sortindex = '0' at update_tables.cgi line 455. [Tue Mar 20 19:59:06 2018] update_tables.cgi: sortindex = '0' at upda +te_tables.cgi line 455. searchfield = 'user_id' at update_tables.cgi line 457. [Tue Mar 20 19:59:06 2018] update_tables.cgi: searchfield = 'user_id' + at update_tables.cgi line 457. statement = 'SELECT * FROM users WHERE user_id = ? ORDER BY ? ASC' at + update_tables.cgi line 462. count = '1' at update_tables.cgi line 473. [Tue Mar 20 19:59:06 2018] update_tables.cgi: count = '1' at update_ta +bles.cgi line 486. Finished print {"DD":"2019-01-30","DP":"2018-12-31","MD":"120.00","MJ" +:"2018-01-30","address1":"1471 Meeks Rd","address2":null,"business":" +JZ Electroplating","city":"Latham","comments":"This is a test entry", +"email":"jze@yahoo.com","forename":"John","id":57,"lastname":"Zinzer" +,"password":"1234","phone_cell":"517-204-1111","phone_home":"517-233- +4378","pin":"JbwmZ","position":"General Member","state":"NJ","user_id +":19,"username":"lms19","zip":"45789-2334"} at update_tables.cgi line + 492.

JSON print works as I captured output in an IFrame for testing.

my $searchResult = $sth->fetchrow_hashref(); my $count = $sth->rows; warn("count = '$count'"); if ($count == 0) { warn("Failed Search: '$searchfield' equal to '$searchterm' "); my %searchFail = ( SearchError => $kind); my $json = JSON->new; $json->canonical(1); $json = encode_json(\%searchFail); print "Content-Type: application/json\n\n"; print $json; warn("Finished print 0 count $json"); exit(1); } #{"SearchError":0} Good else { warn("count = '$count'"); my $json = JSON->new; $json->canonical(1); $json = encode_json($searchResult); print "Content-Type: application/json\n\n"; print $json; warn("Finished print $json"); exit(0); }

Replies are listed 'Best First'.
Re: JSON Return Values
by NetWallah (Canon) on Mar 21, 2018 at 04:56 UTC
    Your JavaScript looks valid. However, according to the documentation at https://api.jquery.com/jQuery.getJSON/, getJSON can fail silently it it encounters JSON errors.

    This article on StackOverflow (and the documentation above) point to a more-error-checked call, using the .fail and .done syntax.

                    Python is a racist language what with it's dependence on white space!

      Thanks.

      I assumed no SON errors because I was able to capture the data in an IFrame:

      var data = {"DD":"2019-01-01","DP":"0000-00-00","MD":"120.00","M +J":"2018-01-01","address1":"1327 North St","address2":"Ste 242","busi +ness":null,"city":"Deluth","comments":"This is an insert test with ac +tion converted to sub calls","email":"tj@resolve.net","forename":"Tre +vor","id":65,"lastname":"Johnson","password":"xmk1041","phone_cell":" +(517) 269-1014","phone_home":"(414) 956-9219","pin":"TbwmJ","position +":"General Member","state":"MN","user_id":65,"username":"bwm65","zip" +:"36925-6647"}; loadJSONFormData(data);

      and load in to form fields using loadJSONFormData(data). <.p>

      So as I said, I assumed no error in the JSON data

      I will explore further

        And checking the console.log reveals:

        Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.xxx.org/httpsdocs/cgi-bin/update_tables.cgi?action=updatetable_167&kind=0&searchterm=19. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

      I would appreciate some insight here:

      I am used to drop downs being bound to database fields

      I have a select drop down on a form used to populate the insert/update query sent to the server.

      <td><select required id="position" name="position" onChange="changeFla +g(1)" > <option value="0">Select <option value="1">Board Member <option value="2">Administration <option value="3">General Member </select></td>

      When I repopulate the form field with JSON

      $('form').loadJSON(data);

      , I expect the data from the database field to be displayed. All the other form input fields are populated correctly.

      By the way, this: onChange="changeFlag(1) is not calling anything. A dummy

      In reading:

      Populating form element Form is populated with JSON object using the following JavaScript call: $('form').loadJSON(data); This call matches object properties with the form elements by name and depending on the type of the form element populates value. Following rules are used while the form elements are populated:

      Multiple selection lists

      When plugin matches property with multiple selection list element, it expect that property is array of values that should be selected in the list. Plugin selects all values in the multi selection list that exist in the property of the JavaScript object.

      Assuming that a "select" control comes under the definition of "Multiple selection lists", it sounds as if it would work and display the applicable JSON content.

      I set up a test with a select where I use a button to change the "value" of the select index and that works fine.

      Evidently, $('form').loadJSON(data), does not address the indexing as implied above.

        Where in your question does Perl come into play?

        I think your question is mostly about jQuery, which is off-topic here. You should first check that sending the appropriate (hard-coded) JSON works. Then you can debug your Perl code until it creates the same JSON.

        If you don't know what the correct JSON to create is, no fudging on the Perl side of the world will help you. You will need jQuery expertise, which certainly can be found. But this is not the forum for jQuery expertise.

        The data back from JSON includes "position":"3" so the information is there.

        The javascript looks good:

        (function ($) { $.fn.loadJSON = function (obj, options) { function setElementValue(element, value, name) { var type = element.type || element.tagName; if (type == null) return; type = type.toLowerCase(); switch (type) { case 'radio': if (value.toString().toLowerCase() == element.valu +e.toLowerCase()) $(element).attr("checked", "checked"); break; case 'checkbox': if (value) $(element).attr("checked", "checked"); break; case 'select-multiple': var values = value.constructor == Array ? value : +[value]; for (var i = 0; i < element.options.length; i++) { for (var j = 0; j < values.length; j++) { element.options[i].selected |= element.opt +ions[i].value == values[j]; } } break; case 'select': case 'select-one': case 'text': case 'hidden': $(element).attr("value", value); break;

        At a loss. I don't see "value as either a global attribute or an attribute of select.

        Attributes defines: value <button>, <input>,

      • , <option>, <meter>, <progress>, <param>

        So it is an attribute of option not select

Re: JSON Return Values
by karlgoethebier (Abbot) on Mar 21, 2018 at 17:52 UTC

    Little complement: Fiddler might be helpful for debugging. Windows and Mac OS X only. See also Fiddler.

    Update: A Linux beta build is also available.

    Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: JSON Return Values
by tultalk (Monk) on Mar 23, 2018 at 17:08 UTC

    Everything working perfectly

    Now on to more detailed enhancements

    DELETE W/O THE ENHANCEMENTS WORKS - ENHANCEMENTS UNTESTED

    "delete" code below is supposed to delete record and if successful grab the next or previous record to send back to populate the originating form. If neither exist send error flag back to caller which is supposed to intercept the "data" looking for flag.

    If previous or next record exist, send that back along with flag added to hash before encoded by JSOAN.

    Same with delete record failure

    I want to intercept the "data" to find the flags, act on them and then remove those flags before sending data on to populate the form. Is there any problem with doing that?

    var inquiryQuery = "http://www.xxxxxx.org/httpsdocs/cgi-bin/upda +te_tables.cgi?action=delete_Record&user_id=" + userid + '"'; var data; $.getJSON(inquiryQuery, function(data){ //Check data for status flag. If flag, remove and send data on t +o form loadJSONFormData(data); });

    Code from perl module

    sub delete_Record { my $userid = $query->param('user_id'); my $json = JSON->new; my $result; my $count; my %success; my $key; my $value; my ($sth, $stmt); warn("Delete record based on user_id = '$userid'"); #Delete the desired record $key = "DeleteRecord"; $stmt = "DELETE FROM users WHERE user_id = ?"; $sth = $dbh->prepare ($stmt) or die "Error Preparing:\n" . $stmt . + "\nDBI returned: \n", $dbh->errstr; $sth->execute ($userid) or die "Unable to execute query: " . $sth- +>errstr; $value = (SELECT ROW_ COUNT()); if ($value == 0) { %success{$key} = $value; #Add "0" FLAG Delete failed no other ac +tion follows $json = JSON->new; $json->canonical(1); $json = encode_json(\%success); print "Content-Type: application/json\n\n"; print $json; warn("Finished print $json"); exit(0); } elsif ($value >= 1) { %success{$key} = $value; #Update FLAG "1" Delete success #check previous record $stmt = "SELECT * FROM users WHERE user_id <= (SELECT MAX(user_i +d) FROM users WHERE user_id < ?) ORDER BY user_id DESC LIMIT 1"; $sth = $dbh->prepare ($stmt) or die "Error Preparing:\n" . $stmt + . "\nDBI returned: \n", $dbh->errstr; $sth->execute ($userid) or die "Unable to execute query: " . $st +h->errstr; $result = $sth->fetchrow_hashref(); $count = $sth->rows; warn("count 1st Pass = '$count'"); if ($count == 0) { #check next record $stmt = "SELECT * FROM users WHERE user_id >= (SELECT MIN(user +_id) FROM users WHERE user_id > ?) ORDER BY user_id ASC LIMIT 1"; $sth = $dbh->prepare ($stmt) or die "Error Preparing:\n" . $st +mt . "\nDBI returned: \n", $dbh->errstr; $sth->execute ($userid) or die "Unable to execute query: " . $ +sth->errstr; $result = $sth->fetchrow_hashref(); $count = $sth->rows; warn("count 2nd Pass = '$count'"); $key ="ReturnedRecord"; if ($count == 0) { warn("No other record must have deleted last one"); %success( $key => $count); #Add "0" FLAG Failed to return ne +w record after successful delete $json->canonical(1); $json = encode_json(\%success); print "Content-Type: application/json\n\n"; print $json; warn("Finished print 0 count $json"); exit(1); } elsif ($count == 1) { warn("count = '$count'"); $json->canonical(1); %success( $key => $count); #Add "1" FLAG return new record s +uccessful %result = (%result, %success); #add %success flags to $resul +t $json = encode_json(\%result); print "Content-Type: application/json\n\n"; print $json; warn("Finished print $json"); exit(0); } } elsif ($count == 1) { warn("count = '$count'"); $json->canonical(1); %result = (%result, %success); #add %success flags to $result + $json = encode_json(\%result); print "Content-Type: application/json\n\n"; print $json; warn("Finished print $json"); exit(0); } } }

      Why not encode a structure than keeps the record data and the flags separate

      my $json = encode_json({ record => $data, ReturnedRecord => $return_count, DeleteRecord => $delete_count });

      then no need to delete anything

      var url = ".../update_tables.cgi"; var param = { "action":"delete_Record", "user_id":userid, }; $.getJSON(url, param, function(data){ if (data.ReturnedRecord){ loadJSONFormData(data.record); } }
      poj

        Pretty slick. Lots of shortcuts particularly the UNION.

        Thanks much

Re: JSON Return Values
by Anonymous Monk on Mar 21, 2018 at 13:22 UTC
    That will turn out to be the problem. All bugs like these must be addressed on the client side, using a browser's debugging features to look at the exact data which was sent and received, and to check the JavaScript console for errors. If you are using a JSON package on the Perl (server) side to generate the response, as of course you should be, then you can rely on the JSON being properly-formatted and so on. So the server side is probably exonerated. But on the client side, many things can "silently fail." Maddeningly, JavaScript will spit out an error-message to its console and keep going.
      Maddeningly, JavaScript will spit out an error-message to its console and keep going.

      I could not possibly disagree more and this sounds like it was written someone who doesn't even have 10 years of experience, let alone 30. JS would stop, even freeze the browser in the early days on meaningless errors and there were no built in, or even optional install, dev panels. That was objectively maddening and why I stayed away from JS for years till the tools and default behavior in browsers improved.

      You can also pause on exceptions/errors and step through the code with all the modern dev panels so there is no excuse for complaining about how JS will keep going. That is a matter of choice for the professional developer.

      Everything working as long as I remember to push the button FireFox

      I guess my real issue is this:

      Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.xxx.org/httpsdocs/cgi-bin/update_tables.cgi?action=updatetable_167&kind=0&searchterm=19. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

      Don't understand "cross origin" since all same domain

      Actually, my problem. Running access from form served up from host, Ok with CORS off. Running on HTML editor is the problem

      Sorry for the shortsightedness