Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print JSON data with Perl without using JSON module?

Tags:

json

mysql

perl

I am trying to write auto-complete for my dictionary project hosted on SourceForge. Unfortunately, Perl on SF does not have JSON module installed. How can I workaround this, without using module itself? As a model I took JQuery UI automcomplete guide on jensbits.

Here is Perl code that is supposed to query text and send to the auto-complete module

#!/usr/bin/perl
use strict;
use CGI;
use DBI;
use JSON;
# HTTP HEADER 
print "Content-type: application/json; charset=iso-8859-1\n\n";

my $dbh = DBI->connect("DBI:mysql:database;mysql_read_default_file=/path/.my.cnf");

$dbh->do("set character set utf8");
$dbh->do("set names utf8");

my ($p, $sth, @query_output); 

$p = new CGI;
my $term = $p->param('term');

$sth = $dbh->prepare(qq{SELECT trim(both char(13) FROM article) AS value, definition FROM dict WHERE article like ?;});
$sth->execute('%'.$term.'%');

# LOOP THROUGH RESULTS
while ( my $row = $sth->fetchrow_hashref ){
push @query_output, $row;
}
#CLOSE THE DATABASE CONNECTION
$dbh->disconnect()
# JSON OUTPUT
print JSON::to_json(\@query_output);
like image 452
Temujin Avatar asked Oct 17 '11 12:10

Temujin


3 Answers

Why not install the module into your user directory on SourceForge using local::lib?

like image 111
Dave Cross Avatar answered Nov 13 '22 10:11

Dave Cross


As far as I know, JSON package doesn't need to be installed in system. You can just download latest JSON distribution, unpack, upload it to your hosting and let Perl know, where to grab the code: just add

use lib '/absolute/path/to/JSON/lib';

before

use JSON;

If you don't know absolute path or want to make the code more portable, you can use FindBin package, to find JSON distro dir relative to your binary:

use FindBin
use lib "$FindBin::Bin/JSON/lib";

I hope this solves your problem.

like image 3
yko Avatar answered Nov 13 '22 08:11

yko


If you really can't install the JSON module, it's not hard to write a bare-bones JSON encoder yourself:

sub to_json {
    my $val = shift;
    if (not defined $val) {
        return "null";
    } elsif (not ref $val) {
        $val =~ s/([\0-\x1f\"\\])/sprintf "\\u%04x", ord $1/eg;
        return '"' . $val . '"';
    } elsif (ref $val eq 'ARRAY') {
        return '[' . join(',', map to_json($_), @$val) . ']';
    } elsif (ref $val eq 'HASH') {
        return '{' . join(',', map to_json($_) . ":" . to_json($val->{$_}), sort keys %$val) . '}';
    } else {
        die "Cannot encode $val as JSON!\n";
    }
}
print to_json($data);

This code will encode undef as null, arrayrefs as JSON arrays, hashrefs as JSON objects, and all defined non-reference scalars as JSON strings. It will die if it encounters anything else; notably, it doesn't map \1 and \0 to true and false like the JSON module does, although this would be easy to add if desired.


As an alternative, Data::Dumper can be made to emit something approximating JSON by setting the appropriate options:

use Data::Dumper ();
print Data::Dumper->new([ $data ])->Pair(':')->Terse(1)->Useqq(1)->Deepcopy(1)->Dump();

However, the resulting output may not be 100% valid JSON; in particular, even with these options, Data::Dumper's handling of undef and of strings containing special or unprintable characters does not fully match the JSON spec.

like image 3
Ilmari Karonen Avatar answered Nov 13 '22 08:11

Ilmari Karonen