Data::Rmap is also an alternative (and is faster in this particular case). But they are both rather slow, so I created
Data::Clean::JSON and
Data::Clean::FromJSON which generate Perl code to do the cleansing and can be several times faster. A benchmark (from slowest to fastest):
% perl -MBench -MStorable=dclone -MData::Dump -MJSON -MData::Visitor::
+Callback -E'
$data=JSON->new->decode(q([null, true, false, 1, 2, 3, "a", "b", [], {
+}])); dd $data;
$v=Data::Visitor::Callback->new("JSON::PP::Boolean"=>sub{$_=$_?1:0}, "
+JSON::XS::Boolean"=>sub{$_=$_?1:0});
bench sub { $data2=dclone($data); $v->visit($data2) }, -1; dd $data2'
[
undef,
bless(do{\(my $o = 1)}, "JSON::XS::Boolean"),
bless(do{\(my $o = 0)}, "JSON::XS::Boolean"),
1,
2,
3,
"a",
"b",
[],
{},
]
4846 calls (3328/s), 1.456s (0.301ms/call)
[undef, 1, 0 .. 3, "a", "b", [], {}]
% perl -MBench -MStorable=dclone -MData::Dump -MJSON -MData::Rmap=rmap
+_ref -E'
$data=JSON->new->decode(q([null, true, false, 1, 2, 3, "a", "b", [], {
+}]));
dd $data;
bench sub { $data2=clone($data); rmap_ref { $_ = ref($_) eq "JSON::PP:
+:Boolean" || ref($_) eq "JSON::XS::Boolean" ? ($_?1:0) : $_ } $data }
+, -1;
dd $data2'
[
undef,
bless(do{\(my $o = 1)}, "JSON::XS::Boolean"),
bless(do{\(my $o = 0)}, "JSON::XS::Boolean"),
1,
2,
3,
"a",
"b",
[],
{},
]
13573 calls (11735/s), 1.157s (0.0852ms/call)
[undef, 1, 0 .. 3, "a", "b", [], {}]
% perl -MBench -MStorable=dclone -MData::Dump -MJSON -MData::Clean::Fr
+omJSON -E'
$data=JSON->new->decode(q([null, true, false, 1, 2, 3, "a", "b", [], {
+}]));
dd $data;
$cleanser=Data::Clean::FromJSON->new;
bench sub { $data2=dclone($data); $cleanser->clean_in_place($data2) },
+ -1;
dd $data2'
[
undef,
bless(do{\(my $o = 1)}, "JSON::XS::Boolean"),
bless(do{\(my $o = 0)}, "JSON::XS::Boolean"),
1,
2,
3,
"a",
"b",
[],
{},
]
33781 calls (32790/s), 1.030s (0.0305ms/call)
[undef, 1, 0 .. 3, "a", "b", [], {}]