Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this how to use hashes with JSON?

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?

like image 727
Sandra Schlichting Avatar asked Jan 19 '23 17:01

Sandra Schlichting


2 Answers

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.

like image 120
Dave Cross Avatar answered Jan 27 '23 11:01

Dave Cross


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.

like image 40
Matt Ball Avatar answered Jan 27 '23 12:01

Matt Ball