YAML :: Tiny не поддерживает JSON :: XS :: Boolean - PullRequest
2 голосов
/ 04 ноября 2011

При чтении некоторых структур данных JSON, а затем при попытке Dump их использования YAML::Tiny иногда возникает ошибка

YAML::Tiny does not support JSON::XS::Boolean

Я понимаю, почему это так (в частности, YAML::Tiny не поддерживает логические значения, которые JSON стремится четко отличить от других скаляров), но есть ли быстрый способ взломать эти JSON::XS::Boolean объекты в простые 0 и 1 только для быстрого вывода на экран?

1 Ответ

3 голосов
/ 05 ноября 2011

YAML :: Tiny не поддерживает объекты.К сожалению, он даже не имеет возможности просто зачеркнуть все объекты, которые будут обрабатывать JSON::XS::Boolean.

Вы можете сделать это довольно легко с помощью рекурсивной функции, хотя:

use strict;
use warnings;
use 5.010; # for say

use JSON::XS qw(decode_json);
use Scalar::Util qw(blessed reftype);
use YAML::Tiny qw(Dump);

my $hash = decode_json('{ "foo": { "bar": true }, "baz": false }');

# Stringify all objects in $hash:
sub stringify_objects {
  for my $val (@_) {
    next unless my $ref = reftype $val;
    if (blessed $val) { $val = "$val" }
    elsif ($ref eq 'ARRAY') { stringify_objects(@$val) }
    elsif ($ref eq 'HASH')  { stringify_objects(values %$val) }
  }
}

stringify_objects($hash);

say Dump $hash;

Эта функция не беспокоит обработку скалярных ссылок, потому что JSON их не создаст.Он также не проверяет, действительно ли объект перегружен строковым форматированием.

Data :: Rmap не подходит для этого, потому что он будет посещать определенный объект только один раз, независимо от того, сколько раз он появляется.Поскольку объекты JSON::XS::Boolean являются синглетонами, это означает, что он найдет только первый true и первый false.Это можно обойти, но это требует углубления в исходный код, чтобы определить, как генерируются ключи в его seen хэше:

use Data::Rmap qw(rmap_ref);
use Scalar::Util qw(blessed refaddr);

# Stringify all objects in $hash:
rmap_ref { if (blessed $_) { delete $_[0]->seen->{refaddr $_};
                             $_ = "$_" } } $hash;

Я думаю, что рекурсивная функция более понятна и не уязвимаизменения в Data::Rmap.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...