为什么YAML在字符串上抛出浮点ArgumentErrors?

时间:2013-04-26 18:01:09

标签: ruby string yaml psych

我在复杂哈希中有一些嵌套字符串,会触发“ArgumentError”异常。处理这个问题最好的方法是什么?

require 'yaml'
{
    a: 'hello',
    b: [{f:'hello',g:Hash.new,i:{a:'hello'}}],
    c: {e:"+."}
}.to_yaml #=> `Float': invalid value for Float(): "+" (ArgumentError) 

完整错误转储:

/Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb:99:in `Float': invalid value for Float(): "+" (ArgumentError)
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb:99:in `tokenize'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:272:in `visit_String'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:324:in `block in visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `each'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:324:in `block in visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `each'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:92:in `push'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych.rb:244:in `dump'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/core_ext.rb:14:in `psych_to_yaml'

2 个答案:

答案 0 :(得分:1)

这似乎是捆绑心理中的一个错误。在第99行修补~/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb

Float(string.gsub(/[,_]|\.$/, ''))

为:

Float(string.gsub(/[,_]|\.$/, '')) rescue ArgumentError

解决了这个问题。这基本上是mental gem以及Ruby 1.9捆绑版本中的内容。

如果您不想修补Ruby,使用psych-1.3.4 gem是另一种选择;请务必require 'psych'而不是'yaml'

gem 'psych', '=1.3.4'
require 'psych'
{a: 'hello', b: [{f:'hello',g:Hash.new,i:{a:'hello'}}], c: {e:"0+."}}.to_yaml
# => "---\n:a: hello\n:b:\n- :f: hello\n  :g: {}\n  :i:\n    :a: hello\n:c:\n  :e: 0+.\n"

答案 1 :(得分:0)

这可以通过一个更简单的例子再现:

"+.".to_yaml

这似乎是与ruby 2.0.0捆绑的心理版本中的一个错误(以及其他版本,我敢肯定):

  when FLOAT
    if string == '.'
      @string_cache[string] = true
      string
    else
      Float(string.gsub(/[,_]|\.$/, ''))
    end

问题在于“+”。看起来像一个有效的浮点数,如+.5。

这在Ruby 2.2.1(或可能是早期版本)中得到修复,它专门检查可能存在前导符号(+或 - )的情况:

  when FLOAT
    if string =~ /\A[-+]?\.\Z/
      @string_cache[string] = true
      string
    else
      Float(string.gsub(/[,_]|\.$/, ''))
    end