加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl和Ruby之间的YAML数据交换问题

发布时间:2020-12-15 23:36:34 所属栏目:大数据 来源:网络整理
导读:我在使用YAML在Perl和 Ruby之间交换数据时遇到了麻烦.我有一些看起来像数字的值:数字,例如1:16. Perl的YAML库(Tiny和XS)将其编码为1:16,不带引号. Ruby的YAML库(Psych)不会将其解释为字符串,而是以某种方式成为Fixnum值4560.我无法弄清楚如何修复任何一方的
我在使用YAML在Perl和 Ruby之间交换数据时遇到了麻烦.我有一些看起来像数字的值:数字,例如1:16.

Perl的YAML库(Tiny和XS)将其编码为1:16,不带引号. Ruby的YAML库(Psych)不会将其解释为字符串,而是以某种方式成为Fixnum值4560.我无法弄清楚如何修复任何一方的转换问题.

我的用例的YAML中的每个值都应该是一个对象或字符串.所以,如果存在这样的选项,我可以告诉Perl YAML库引用所有值.或者有没有办法告诉Ruby YAML库将所有值都解释为字符串?有任何想法吗?

改变任何一方的语言在逻辑上都不是一种选择.

Perl的:

use YAML::XS qw(DumpFile);
my $foo={'abc'=>'1:16'};
DumpFile('test.yaml',$foo);

ruby:

require('yaml')
foo=YAML.load_file('test.yaml')
puts(foo['abc'])

Ruby代码将打印4560.其中一条评论了解了如何从1:16获得4560,它是1小时,16分钟转换为秒.呃,好的.

解决方法

根据 Yaml 1.1 spec,1:16是sexagesimal(base 60)格式的整数.

另见http://yaml.org/type/int.html,其中说:

Using “:” allows expressing integers in base 60,which is convenient for time and angle values.

包含在Ruby,Psych,recognises this format and converts the value into an integer中的Yaml解析器(错误地,1:16应该是71 – Psych代码似乎认为所有这些值都将采用以下形式:b:c但正则表达式不强制执行). Perl发射器(至少我测试过的YAML :: XS)无法识别这种格式,所以在编写文件时不引用字符串. YAML :: XS确实识别并引用一些整数,但不是全部. YAML :: XS也不承认Psych所做的许多其他格式(例如日期).

(似乎是sexagesimal格式has been removed from the Yaml 1.2 spec.)

Psych在解析时提供了相当大的灵活性–YAML.load_file只是常见用例的简单接口.

您可以使用Psych的解析方法来创建yaml的树表示,然后使用自定义ScalarScanner(将某些格式的字符串转换为适当的Ruby类型的对象)将其转换为Ruby数据结构:

require('yaml')

class MyScalarScanner < Psych::ScalarScanner
  def tokenize string
    #this is the same regexp as Psych uses to detect base 60 ints:
    return string if string =~ /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
    super
  end
end

tree = YAML::parse_file 'test.yaml'
foo = Psych::Visitors::ToRuby.new(MyScalarScanner.new).accept tree

这基本上与使用YAML.load_file时发生的过程相同,只是它使用自定义的扫描程序类.

类似的替代方案是打开ScalarScanner并将tokenize方法替换为自定义方法.这将允许您使用更简单的load_file接口,但有关于猴子修补类的常见警告:

class Psych::ScalarScanner
  alias :orig_tokenize :tokenize
  def tokenize string
    return string if string =~ /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
    orig_tokenize string
  end
end

foo = YAML.load_file 'test.yaml'

请注意,这些示例仅考虑格式为1:16的值.根据您的Perl程序发出的内容,您可能还需要覆盖其他模式.你可能想要看到的一个特别是性感浮动(例如1:16.44).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读