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

これは、同梱されている psych のバグのようです。~/.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 に答える