#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3

    How to return a JSON-encoded array from a Perl script to HTML page?


    Hi, I am working with WAMP in my C drive, and I tested a few Perl files from the cgi-bin folder, it works. However, if I keep a HTML file in the www folder, and on clicking a button in it, I want it to invoke a Perl script through Ajax that should return a JSON-encoded array. It is very easy to do so in PHP, can anybody tell me how to do it in Perl?
  2. #2
  3. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,264
    Rep Power
    1810
    Not hard in perl either. Use one of the JSON modules from CPAN.

    When I've needed to do this, I usually use CGI::Application to create a simple framework. That way, a single script can respond to many different types of requests. One of the nice things about using that framework, is that it is supported by a lot of plug-ins, such as one to output JSON.

    CGI/Application/Plugin/JSON.pm

    Sorry I don't have time for a longer example right now. One of the simple JSON modules should do what you need easily.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3
    No, the main problem is how to configure the settings i.e. where to keep the Perl script, whether in the CGI-BIN folder while the HTML file is anywhere, or both together in any folder, or whether any change to be made in the Apache directives. Also do I need to install Perl in Wamp for this purpose, or will it be ok if it is installed in C:\\Perl while Wamp is in C:\\Wamp.
  6. #4
  7. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,264
    Rep Power
    1810
    I don't use Windows, so I can't answer any questions about Windows confuration; sorry.

    I can say this much: the HTML file can be anywhere than can be reached by the web server. The javascript on the page will make a request to the perl script which must be reachable through a web server. The HTML file and perl server do not need to be in the same directory.

    The easiest way to make the perl script accessible through the web server is by placing it in the cgi-bin directory, but that isn't the only way.

    In the case of a CGI::Application, the perl script that lives in cgi-bin is very basic. As an example:
    Code:
    use MyApp;
    my $app = MyApp->new();
    $app->run();
    The MyApp.pm file is loaded from @INC, so it can be anywhere in your filesystem that you have set up to store perl modules.

    All the parameter reading, dispatching, etc; takes place from that other perl module.

    In that sort of example, the javascript would be making its requests to /cgi-bin/myapp.cgi, but your perl module stored elsewhere would be processing the data and replying.

    ---

    But a perl file stored in /cgi-bin could do all the processing itself, and reply directly.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3
    Can you please provide a basic example where a Perl script is invoked via Ajax, and the script returns an integer value, which is received by Javascript, and subsequently printed out in HTML page?
  10. #6
  11. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,264
    Rep Power
    1810
    I can after work, if it can wait a few hours.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3
    Of course it can. Take your time. Thanks.
  14. #8
  15. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,264
    Rep Power
    1810
    OK, we'll just use the simple JSON.pm module rather than CGI::Application; but I've installed JSON::XS as well, which the JSON module will use to speed things up when available.

    I took my example from a JQuery website tutorial. I love JQuery. Hope the example is suitable for your purposes.

    So the basic HTML page is so:

    HTML Code:
    <!DOCTYPE html>
    <html>
    	<head>
    		<title>AJAX Test</title>             
    		<script type="text/javascript" src="/js/jquery.js"></script>          
    		<script type="text/javascript">                                         
    			$(document).ready(function() {
    			   // generate markup
    			   $("#rating").append("Please rate: ");
     
    			   for ( var i = 1; i <= 5; i++ ) {
    			     $("#rating").append("<a href='#'>" + i + "</a> ");
    			   }
     
    			   // add markup to container and apply click handlers to anchors
    			   $("#rating a").click(function(e) {
    			     // stop normal link click
    			     e.preventDefault();
     
    			     // send request
    			     $.post("/cgi-bin/rate.cgi", {rating: $(this).html()}, function(data) {
    			       // format and output result
    			       $("#rating").html(
    			         "Thanks for rating, current average: " +
    			         data.average + ", number of votes: " + data.count
    			       );
    			     });
    			   });
    			 });
    		</script>                                                               
    	</head>                                                                 
    	<body>                                                                  
    		<h3>Test Page</h3>
    		<div id="rating"></div>
    	</body>                                                                 
    </html>

    The page loads the base jquery library, and has the script from the tutorial embedded. The javascript alters the div to add some rating tags, and when a rating is clicked I've told it to post the rating to my perl script: '/cgi-bin/rate.cgi'

    My perl script:

    perl Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    use CGI qw/:standard/;
    use JSON;
    use Storable;
    use List::Util qw(sum);
     
    # we'll store user rating clicks in the /tmp directory
    my $store = '/tmp/ratings';
     
    my $q = CGI->new;
    print $q->header('application/json');
     
    # get any earlier ratings
    my $ratings = [];
    $ratings = retrieve($store) if -e $store;
     
    # get the new user rating from the javascript
    my $rating = $q->param('rating');
    exit unless $rating;
     
    # add it to our list
    push @$ratings, $rating;
    store($ratings, $store);
     
    my $sum = sum(@$ratings);
    my $count = scalar @$ratings;
    my $average = sprintf("%.1f", ($sum / $count));
     
    #put the data we want to send back into a hash reference
    my $json->{'average'} = $average;
    $json->{'count'} = $count;
     
    # convert and output
    print to_json($json);


    The only non-standard module is JSON, so you'll have to install that. The other modules are in perl core, so you should have them. I used Storable.pm in lieu of a database, or some other file storage. I'm just storing an array reference called $ratings in the /tmp directory (if you're on a *nix, it's a handy place to store junk that will persist until reboot).

    Comments on this post

    • Winters agrees
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3
    Thanks. Will try it and let you know the results. Two points however, will this work if Perl is not installed in the same location as Wamp? And secondly, you are appending the contents of the links inside the div after page load, so a click event won't work on those links, cause they were not present at page-load. You will have to attach the click event either through delegate or live. And yes, I love jQuery!
  18. #10
  19. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,264
    Rep Power
    1810
    will this work if Perl is not installed in the same location as Wamp?
    What do you mean by "same location"? Same directory? Same computer?

    When Apache gets a request to the cgi-bin directory, it will execute that code through the system. The system gives the results back to Apache, and they are sent on to the client. So the computer that Apache is loaded on needs to know how to execute a perl file. Apache and perl don't have to be in the same directory, but perl has to be on the system, and the computer should know to associate the file with the perl interpreter.

    you are appending the contents of the links inside the div after page load, so a click event won't work on those links, cause they were not present at page-load. You will have to attach the click event either through delegate or live.
    Gosh, why is my example working for me? Am I misunderstanding how you need it to work?

    The jQuery script came straight from their tutorial page at the link I provided. I wasn't feeling very creative so I just took their code and made it work with a perl back-end, because your question was about how to get perl to provide a JSON response. So, there's one way. I don't mind working up a different example if you have a specific need.

    If your question is about how to configure Apache on Windows to serve perl files through CGI, you should start a new thread, maybe in the Apache forum rather than perl. I don't use Windows, so I can't say.
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2012
    Posts
    62
    Rep Power
    3
    Yeah Wamp knows that Perl is installed in the computer, for the Perl files located there show the ActivePerl icon. And yes, I really don't know how your code is working! Will try it and let you know whether this works!

IMN logo majestic logo threadwatch logo seochat tools logo