Perl和Ruby之间的YAML数据交换问题
我在使用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,其中说:
包含在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). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |