I have a query on a PostgreSQL system returning a boolean:
my $sth = $dbh->prepare("select 'f'::boolean");
$sth->execute;
my @vals = $sth->fetchrow_array;
According to the DBD::Pg docs,
The current implementation of
PostgreSQL returns ‘t’ for true and
‘f’ for false. From the Perl point of
view, this is a rather unfortunate
choice. DBD::Pg therefore translates
the result for the BOOL data type in a
Perlish manner: ‘f’ becomes the number
0 and ‘t’ becomes the number 1. This
way the application does not have to
check the database-specific returned
values for the data-type BOOL because
Perl treats 0 as false and 1 as true.
You may set the pg_bool_tf attribute
to a true value to change the values
back to ‘t’ and ‘f’ if you wish.
So, that statement should return a 0, which it does, so long as pg_bool_tf returns 0, which it does. However, somewhere along the way JSON::XS (and plain JSON) interprets the returned 0 as a string:
use JSON::XS qw(encode_json);
my $options =
{
layout => 0,
show_widget_help => $vals[0] // 1,
};
die encode_json($options);
…dies with:
{“layout”:0,”show_widget_help”:”0″}
…which would be fine, except that my JavaScript is expecting a boolean there, and the non-empty string “0” gets evaluated to true. Why is the latter 0 quoted and the former not?
According to the JSON::XS docs, this is a main feature:
round-trip integrity
When you serialise a perl data
structure using only data types
supported by JSON, the deserialised
data structure is identical on the
Perl level. (e.g. the string “2.0”
doesn’t suddenly become “2” just
because it looks like a number). There
minor are exceptions to this, read the
MAPPING section below to learn about
those.
…which says:
Simple Perl scalars (any scalar that
is not a reference) are the most
difficult objects to encode: JSON::XS
will encode undefined scalars as JSON
null values, scalars that have last
been used in a string context before
encoding as JSON strings, and anything
else as number value.
But I never use @vals[0] in a string context. Maybe DBD::Pg uses its boolean 0 as a string somewhere before returning it?
The
JSON::XSdoc says the following will be converted totrue/false0and1, ie.\0and\1JSON::XS::trueandJSON::XS::falseUsing one of these should solve your problem