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