【问题标题】:YAML::Tiny does not support JSON::XS::BooleanYAML::Tiny 不支持 JSON::XS::Boolean
【发布时间】:2011-12-22 03:38:18
【问题描述】:

当读取一些 JSON 数据结构,然后尝试使用 YAML::Tiny Dump 它们时,有时会出现错误

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

我明白为什么会这样(特别是 YAML::Tiny 不支持布尔值,JSON 热衷于与其他标量清楚地区分),但是有没有快速的技巧可以将这些 JSON::XS::Boolean 对象变成普通的0's 和 1's 只是为了快速转储到屏幕上?

【问题讨论】:

    标签: json perl yaml


    【解决方案1】:

    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的变化影响。

    【讨论】:

    • 我添加了一个与此相关的问题作为答案,以便我可以发布代码。
    • Hmm.. 实际上,如果其中一个值(例如true)出现不止一次,它就不起作用。由于某种原因,只有第一个布尔值被字符串化。知道为什么吗?
    • @JuanAntonio,这是因为只有一个 true 对象和一个 false 对象。 JSON::XS 只是多次引用它。请参阅我的更新答案。
    • @cjm,谢谢!这几乎就是我最终所做的。感谢您的解决方案!
    猜你喜欢
    • 1970-01-01
    • 2017-08-13
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多