At work, we've been bitten by a weird bug. It could be reduced to the following short code:
#!/usr/bin/perl use warnings; use strict; use Cpanel::JSON::XS; { package My::Package; use Moose; has attr => ( is => 'ro', isa => 'Bool' ); __PACKAGE__->meta->make_immutable; } my $obj = 'My::Package'->new(attr => Cpanel::JSON::XS::true());
which fails with
Attribute (attr) does not pass the type constraint because: Validation + failed for 'Bool' with value JSON::PP::Boolean=SCALAR(0x1dc1558) at +constructor My::Package::new (defined at 1.pl line 15) line 31

(The false() function works correctly.)

The problem seems to be reported as the #61 on Cpanel::JSON::XS's GitHub. But I'm not sure the real problem lies in the JSON module. Does Moose play right?

If we look at the relevant code, we can see (in Moose/Util/TypeConstraints/Builtins.pm):

subtype 'Bool' => as 'Item' => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq +'0' } => inline_as { '(' . '!defined(' . $_[1] . ') ' . '|| ' . $_[1] . ' eq "" ' . '|| (' . $_[1] . '."") eq "1" ' . '|| (' . $_[1] . '."") eq "0"' . ')' };

The problem is that the JSON booleans overload both stringification and string equality (from Cpanel/JSON/XS.pm):

&overload::import( 'overload', # workaround 5.6 reserved keyword war +ning "0+" => sub { ${$_[0]} }, "++" => sub { $_[0] = ${$_[0]} + 1 }, "--" => sub { $_[0] = ${$_[0]} - 1 }, '""' => sub { ${$_[0]} == 1 ? 'true' : '0' }, # GH 29 'eq' => sub { my ($obj, $op) = ref ($_[0]) ? ($_[0], $_[1]) : ($_[1], $_[0]); if ($op eq 'true' or $op eq 'false') { return "$obj" eq 'true' ? 'true' eq $op : 'false' eq $op; } else { return $obj ? 1 == $op : 0 == $op; } }, fallback => 1);

But Moose first stringifies the object before calling eq, i.e. it bypasses any eq overloading on a Bool object. The json true stringifies to "true" which isn't equal to "1", but

Cpanel::JSON::XS::true() eq '1';

returns true because of the overloaded eq.

So, whom should I report the bug to?

Update: Yes, I know I can coerce the Moose boolean from the JSON boolean:

{ use Moose::Util::TypeConstraints; my $class = ref Cpanel::JSON::XS::true(); class_type($class); coerce Bool => from $class => via { !! $_ }; } #... has attr => ( is => 'ro', isa => 'Bool', coerce => 1 );

But wasn't the whole point of the overloading in the JSON library to avoid such things and make it possible to use it directly with the correct behaviour based on the context?

Update 2: Similar problem was reported to Moose as a bug, but was rejected.

($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

In reply to Cpanel::JSON::XS::true and Moose don't play well together by choroba

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.