DBM::Deep не может импортировать hashref со значениями 'true' или 'false'

У меня есть JSON текст как дано ниже:

test.json

{
  "a" : false
}

Я хочу создать DBM::Deep хеш для выше JSON. Мой код выглядит так, как указано ниже:

dbm.pl

use strict;
use warnings;

use DBM::Deep;
use JSON;
use Data::Dumper;

# create the dbm::deep object
my $db = DBM::Deep->new(
    file => 'test.db',
    type => DBM::Deep->TYPE_HASH
);

my $json_text = do {
    open( my $json_fh, $path )
      or die("Can't open \$path\": $!\n");
    local $/;
    <$json_fh>;
};

my $json = JSON->new;
my $data = $json->decode($json_text);
print Dumper($data);

# create dbm::deep hash
eval { $db->{$path} = $data; };

if ($@) {
    print "error : $@\n";
}

Я получаю ниже вывод / ошибка при выполнении вышеуказанного кода:

ошибка

$VAR1 = { 'a' => благослови ( do{(my $o = 0)}, 'JSON::XS::Boolean') }; ошибка: DBM::Deep: хранение ссылок типа 'SCALAR' не поддерживается. на линии 26 дБм.пл

Похоже, что JSON внутренне использует JSON:: XS, который преобразует "истинное" значение в объект JSON:: XS:: Boolean, а DBM:: Deep не может это обработать, хотя может обрабатывать нулевое значение.

Хотя приведенный выше код работает нормально для следующих входов:

{
  "a" : 'true'  # if true is in quotes
}

или же

{
  "a" : null 
}

Я много чего перепробовал, но ничего не получалось. У кого-нибудь есть обходной путь?

2 ответа

Решение

Парсер JSON, который вы используете, помимо прочего, возвращает объект, который работает как логическое значение, когда встречается true или же false в JSON. Это позволяет перекодировать данные в JSON без изменений, но это может вызвать проблемы такого рода.

null не имеет этой проблемы, потому что Perl имеет собственное значение (undef), который может быть использован, чтобы представить это однозначно.

Следующие преобразовать эти объекты в простые значения.

 sub convert_json_bools {
    local *_convert_json_bools = sub {
        my $ref_type = ref($_[0])
            or return;

        if ($ref_type eq 'HASH') {
            _convert_json_bools($_) for values(%{ $_[0] });
        }
        elsif ($ref_type eq 'ARRAY') {
            _convert_json_bools($_) for @{ $_[0] };
        }
        elsif ($ref_type =~ /::Boolean\z/) {
            $_[0] = $_[0] ? 1 : 0;
        }
        else {
            warn("Unsupported type $ref_type\n");
        }
    };

    &_convert_json_bools;
}

convert_json_bools($data);

Ваш код работает нормально для меня, единственное изменение заключается в установке

my $path = 'test.json';

Вы должны проверить номера версий вашего модуля. Это те, которые у меня есть

print $DBM::Deep::VERSION, "\n";    # 2.0013
print $JSON::VERSION, "\n";         # 2.90
print $JSON::XS::VERSION, "\n";     # 3.02

и я использую Perl v5.24.0

Вывод сброса выглядит следующим образом

Вновь созданный DBM::Deep база данных

$VAR1 = bless( {}, 'DBM::Deep::Hash' );

вывод $json->decode

$VAR1 = {
          'a' => undef
        };

населенный DBM::Deep база данных после eval

$VAR1 = bless( {
                 'test.json' => bless( {
                                         'a' => undef
                                       }, 'DBM::Deep::Hash' )
               }, 'DBM::Deep::Hash' );

Все это выглядит так, как должно

Другие вопросы по тегам