3

我在触发“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'
4

2 回答 2

1

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

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

至:

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

解决了这个问题。这基本上是 psych 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"
于 2013-04-26T19:08:45.403 回答
0

这可以用一个更简单的例子来重现:

"+.".to_yaml

这似乎是与 ruby​​ 2.0.0 捆绑在一起的 psych 版本中的一个错误(我敢肯定,还有其他版本):

  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
于 2015-04-14T17:23:15.203 回答