Памятуя о проблемах с числами, которые на самом деле строки, программист написал фукнцию, которая рекурсивно обходит переданную ей структуру данных и in-place нумерифицирует строки, похожие на числа.
use Scalar::Util qw(looks_like_number);
# было {"1":"c","3":["1","b",3],"d":"5"}
# стало {"1":"c","3":[1,"b",3],"d":5}
# ключи хешей не трогаем -- в json они всегда строки
# можно пользоваться так: print to_json(numerify($data));
sub numerify
{
my $data = shift;
if (ref $data eq ""){
if ( looks_like_number($data) ){
$data += 0;
}
} elsif ( ref $data eq 'ARRAY' ){
numerify($_) for @$data;
} elsif ( ref $data eq 'HASH' ) {
numerify($_) for values %$data;
}
return $data;
}
Но что-то тут не заладилось…
print to_json(numerify({1=>'c', 3=> ['1','b',3], d=>"5"}));
{"1":"c","3":["1","b",3],"d":"5"}
Выглядит так, будто нумерификация вообще не работает.
Any arguments passed in show up in the array @_. (...) The array @_ is a local array, but its elements are aliases for the actual scalar parameters. (...) Because the assignment copies the values, this also has the effect of turning call-by-reference into call-by-value. perldoc perlsub
Любые аргументы, передаваемые в подпрограму Perl, поступают в нее в виде массива @_. (...) Массив @_ является локальным, но его значения служат псевдонимами для реальных скалярных параметров. (...) Копирование значений заменяем семантику передачи по ссылке семантикой передачи по значению.
Проблема в строчке
my $data = shift;
Здесь создается локальная для функции копия входного параметра, и когда рекурсия спускается до скалярных значений, нумерификация путем сложением с 0 производится именно над локальной копией скаляра, не затрагивая исходное значение.
Чтобы действительно поменять переданную структуру, стоит работать
непосредственно с элементами массива @_
:
sub numerify_good
{
if (ref $_[0] eq ""){
if ( looks_like_number($_[0]) ){
$_[0] += 0;
}
} elsif ( ref $_[0] eq 'ARRAY' ){
numerify_good($_) for @{$_[0]};
} elsif ( ref $_[0] eq 'HASH' ) {
numerify_good($_) for values %{$_[0]};
}
return $_[0];
}
Самое точное и полное объяснение проблемы прислал наш читатель Роман Луговкин. Здорово!
Еще на тему кавычек в json: топик на StackOverflow