Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,21 @@ my %META = (
my %MM_ARGS = ();

if (! parse_args()->{PUREPERL_ONLY}) {
# we require Cpanel::JSON::XS, except if JSON::XS is already installed.
# we require Cpanel::JSON::XS, except if
# (JSON::XS is already installed and its use dictated by env var).
# (we also always recommend Cpanel::JSON::XS, just to make sure.)
$MM_ARGS{PREREQ_PM}{'Cpanel::JSON::XS'} = '2.3310'
if eval { require Cpanel::JSON::XS; 1 }
if eval { require Cpanel::JSON::XS }
or (
not eval { require JSON::XS; 1; }
$ENV{PERL_JSON_XS_USE}
and not eval { require JSON::XS }
and can_compile_loadable_object(quiet => 1)
);

# JSON::XS 3 changed its boolean handling - update it
# if JSON::XS is installed and < 3.0
# if JSON::XS is installed and < 3.0 and JSON::XS use dictated by env var
$MM_ARGS{PREREQ_PM}{'JSON::XS'} = '3.00'
if eval { require JSON::XS; 1 }
if $ENV{PERL_JSON_XS_USE} and eval { require JSON::XS }
and not eval { JSON::XS->VERSION('3.0'); 1 };
}

Expand Down
35 changes: 23 additions & 12 deletions lib/JSON/MaybeXS.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ $VERSION = eval $VERSION;

sub _choose_json_module {
return 'Cpanel::JSON::XS' if $INC{'Cpanel/JSON/XS.pm'};
return 'JSON::XS' if $INC{'JSON/XS.pm'};
return 'JSON::XS' if $INC{'JSON/XS.pm'} and $ENV{PERL_JSON_XS_USE};

my @err;

return 'Cpanel::JSON::XS' if eval { require Cpanel::JSON::XS; 1; };
return 'Cpanel::JSON::XS' if eval { require Cpanel::JSON::XS };
push @err, "Error loading Cpanel::JSON::XS: $@";

return 'JSON::XS' if eval { require JSON::XS; 1; };
push @err, "Error loading JSON::XS: $@";
return 'JSON::XS' if $ENV{PERL_JSON_XS_USE} and eval { require JSON::XS };
push @err, "Error loading JSON::XS: $@" if $ENV{PERL_JSON_XS_USE};

return 'JSON::PP' if eval { require JSON::PP; 1 };
return 'JSON::PP' if eval { require JSON::PP };
push @err, "Error loading JSON::PP: $@";

die join( "\n", "Couldn't load a JSON module:", @err );
Expand Down Expand Up @@ -101,7 +101,7 @@ sub to_json ($@) {

=head1 NAME

JSON::MaybeXS - Use L<Cpanel::JSON::XS> with a fallback to L<JSON::XS> and L<JSON::PP>
JSON::MaybeXS - Use L<Cpanel::JSON::XS> with a fallback to maybe L<JSON::XS>, and L<JSON::PP>

=head1 SYNOPSIS

Expand All @@ -118,9 +118,11 @@ JSON::MaybeXS - Use L<Cpanel::JSON::XS> with a fallback to L<JSON::XS> and L<JSO
=head1 DESCRIPTION

This module first checks to see if either L<Cpanel::JSON::XS> or
L<JSON::XS> is already loaded, in which case it uses that module. Otherwise
it tries to load L<Cpanel::JSON::XS>, then L<JSON::XS>, then L<JSON::PP>
in order, and either uses the first module it finds or throws an error.
L<JSON::XS> is already loaded (but see L<note|/"NOTE ON JSON::XS">),
in which case it uses that module. Otherwise it tries to load
L<Cpanel::JSON::XS>, then L<JSON::XS> (see L<note|/"NOTE ON JSON::XS">),
then L<JSON::PP> in order, and either uses the first module it finds or
throws an error.

It then exports the C<encode_json> and C<decode_json> functions from the
loaded module, along with a C<JSON> constant that returns the class name
Expand Down Expand Up @@ -202,6 +204,11 @@ Since this is a bare sub in the various backend classes, it cannot be called as
a class method like the other interfaces; it must be called as a function, with
no invocant. It supports the representation used in all JSON backends.

=head1 NOTE ON JSON::XS

As of version 1.003010, JSON::MaybeXS will not use L<JSON::XS> unless
the environment variable C<PERL_JSON_XS_USE> is set to a true value.

=head1 CONSTRUCTOR

=head2 new
Expand Down Expand Up @@ -281,9 +288,13 @@ Alternatively, you can use duck typing:

At installation time, F<Makefile.PL> will attempt to determine if you have a
working compiler available, and therefore whether you are able to run XS code.
If so, L<Cpanel::JSON::XS> will be added to the prerequisite list, unless
L<JSON::XS> is already installed at a high enough version. L<JSON::XS> may
also be upgraded to fix any incompatibility issues.
If so, L<Cpanel::JSON::XS> will be added to the prerequisite list.

If and only if the environment variable C<PERL_JSON_XS_USE> is set
to a true variable, then unless L<JSON::XS> is already installed at
a high enough version. L<JSON::XS> may also be upgraded to fix any
incompatibility issues. If that environment variable is not set to a
true value, L<JSON::XS> will be ignored.

Because running XS code is not mandatory and L<JSON::PP> (which is in perl
core) is used as a fallback backend, this module is safe to be used in a suite
Expand Down
14 changes: 12 additions & 2 deletions t/none.t
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
use strict;
use warnings;

my @BACKENDS;
BEGIN {
@BACKENDS = (
'Cpanel/JSON/XS.pm',
($ENV{PERL_JSON_XS_USE} ? 'JSON/XS.pm' : ()),
'JSON/PP.pm',
);
}

# hide Cpanel::JSON::XS, JSON::XS, JSON::PP
use lib map {
my $m = $_;
sub { return unless $_[1] eq $m; die "Can't locate $m in \@INC (hidden).\n" };
} qw{Cpanel/JSON/XS.pm JSON/XS.pm JSON/PP.pm};
} @BACKENDS;

use Test::More 0.88;

ok(!eval { require JSON::MaybeXS; 1 }, 'Class failed to load');

my $re_string = join '.*', map quotemeta("Can't locate $_"), @BACKENDS;
like(
$@, qr{Can't locate Cpanel/JSON/XS\.pm.*Can't locate JSON/XS\.pm.*Can't locate JSON/PP\.pm}s,
$@, qr{$re_string}s,
'All errors reported'
);

Expand Down
1 change: 1 addition & 0 deletions t/preload_xs.t
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use strict;
use warnings;

use if !$ENV{PERL_JSON_XS_USE}, 'Test::More', skip_all => 'No JSON::XS override';
use if !eval { require JSON::XS; 1; }, 'Test::More', skip_all => 'No JSON::XS';
use Test::More 0.88;
use JSON::MaybeXS;
Expand Down
2 changes: 1 addition & 1 deletion t/xs.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use lib map {
use Test::More 0.88;
use JSON::MaybeXS;

unless ( eval { require JSON::XS; 1 } ) {
unless ( $ENV{PERL_JSON_XS_USE} and eval { require JSON::XS; 1 } ) {
plan skip_all => 'No JSON::XS';
}

Expand Down