YAML::Tiny 不支持 JSON::XS::Boolean

发布于 2024-12-13 17:37:00 字数 355 浏览 0 评论 0原文

当读取一些 JSON 数据结构,然后尝试使用 YAML::Tiny转储它们时,我有时会收到错误

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

,我理解为什么会出现这种情况(特别是 >YAML::Tiny 不支持布尔值,而 JSON 热衷于与其他标量明确区分开来),但是有没有快速的技巧可以将这些 JSON::XS: :Boolean 对象转换为普通对象01 只是为了快速转储到屏幕?

When reading some JSON data structures, and then trying to Dump them using YAML::Tiny, I sometimes get the error

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

I understand why this is the case (in particular YAML::Tiny does not support booleans, which JSON is keen to clearly distinguish from other scalars), but is there a quick hack to turn those JSON::XS::Boolean objects into plain 0's and 1's just for quick dump-to-the-screen purposes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花期渐远 2024-12-20 17:37:00

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;

我认为递归函数更清晰,并且不易受到 中的更改的影响>数据::Rmap

YAML::Tiny doesn't support objects. Unfortunately, it doesn't even have an option to just stringify all objects, which would handle JSON::XS::Boolean.

You can do that fairly easily with a recursive function, though:

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;

This function doesn't bother processing scalar references, because JSON won't produce them. It also doesn't check whether an object actually has overloaded stringification.

Data::Rmap doesn't work well for this because it will only visit a particular object once, no matter how many times it appears. Since the JSON::XS::Boolean objects are singletons, that means it will only find the first true and the first false. It's possible to work around that, but it requires delving into the source code to determine how keys are generated in its seen hash:

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;

I think the recursive function is clearer, and it's not vulnerable to changes in Data::Rmap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文