I am making a webpage, where there are two forms (users and owners), where one can type comma separated names in each form, and hit Submit.
I have tried to use JSON before with strings only, without using a Perl module. Now I need to transfer information for many users in the form of username, full name and owner_name, full name. In Perl I have this as two hashes.
This is a two part question.
Server side
This is my Perl script.
#!/usr/bin/perl -T
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard);
use JSON;
use utf8;
use strict;
use warnings;
my $cgi = CGI->new;
$cgi->charset('UTF-8');
my @owners = map { s/\s*//g; $_ } split ",", $cgi->param('owner');
my @users  = map { s/\s*//g; $_ } split ",", $cgi->param('users');
# ...
my %user_result = ();
foreach my $u (@users) {
    $user_result{$u} = $db1->{$u}{displayName};
}
my %owner_result = ();
foreach my $o (@owners) {
    $owner_result{$o} = $db2{$o}{ad_displayname};
}
my $json->{"users"}  = \%user_result;
my $json->{"owners"} = \%owner_result;
my $json_string = to_json($json);
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json_string;
Is this the correct way to make the two hashes into a JSON string?
Client side
$(document).ready(function(){
    $('form').live('submit', function(){
    $.ajax({
        type: "GET",
        url: "/cgi-bin/ajax.pl",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: $(this).serialize(),
        error: function(XMLHttpRequest, textStatus, errorThrown) { 
        $('div#create_result').text("responseText: " + XMLHttpRequest.responseText +
                        ", textStatus: " + textStatus +
                        ", errorThrown: " + errorThrown);
        $('div#create_result').addClass("error");
        },
        success: function(result){
        if (result.error) {
            $('div#create_result').text("result.error: " + result.error);
            $('div#create_result').addClass("error");
        } else { // perl script says everything is okay
              // how do I access my two hashes here?
              // {"users": [username1, fullname1, ...], "owners": [owner name1, full name 1, ...]}
              var users  = result.users;    // array
              var owners = result.owners;   // array
              alert(users);
              alert(owners);
        }
        }
    });
    });
});
Is this the correct way to send and receive the JSON?
And how do I access data afterwards?
Update
Updated code with Matt Ball and davorg answers and added alert(users).
The bug right now is that the json object isn't defined.
my $json->{"users"}  = \%user_result;
my $json->{"owners"} = \%owner_result;
How do I define such?
You're attempting to print two CGI header blocks. Unfortunately, you can only have a single CGI block associated with each response. And, unfortunately, the first header block you print has the wrong content-type header (it's 'text/html' where you actually want 'application/json').
If you remove the 'print "Content-Type: ..."' line, things should work a bit better.
Then in the second header block, you're trying to call an unknown function called "header". That's actually a method on your $cgi object, so it needs to be called as $cgi->header(...).
Those fixes should actually get some JSON back to your client code successfully. There are a couple of other suggestions I'd make though.
1/ The first argument to the 'split' function should be a regular expression, not a string.
2/ The JSON data structures you are building seem unnecessarily complex. For each of your two sections (users and owners) you have a single element array which contains a reference to a hash. Surely the array can be omitted so each element just contains the hash reference directly.
With dataType: 'json', jQuery will automagically parse the JSON result for you. That means that the result value passed into the success callback is already a proper JavaScript object. You can access its values just like you would any other JS object. For example, if the Perl script returns this JSON:
{"foo": "a", "bar": 42, "baz": [true, false]}
Then you can access the various fields in the success callback like so:
success: function(result) {
    var foo = result.foo,    // 'a'
        bar = result.bar,    // 42
        baz = result.baz;    // [true, false]
}
If you set Content-Type: application/json in the response header (in Perl) you don't even need the dataType: 'json' because jQuery can sniff the data type from the HTTP Content-Type header.
I don't know Perl, so I can't help you on that side.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With