2013-05-02 57 views
3

我想检查一个字符串是否有效YAML。我想从我的Ruby代码中用宝石或库来做到这一点。我唯一有此开始/救援条款,但它并没有得到适当的抢救:如何检查字符串是否有效YAML?

def valid_yaml_string?(config_text) 
    require 'open-uri' 
    file = open("https://github.com/TheNotary/the_notarys_linux_mint_postinstall_configuration") 
    hard_failing_bad_yaml = file.read 
    config_text = hard_failing_bad_yaml 
    begin 
    YAML.load config_text 
    return true 
    rescue 
    return false 
    end 
end 

我遗憾的是越来越可怕的错误:

irb(main):089:0> valid_yaml_string?("b") 
Psych::SyntaxError: (<unknown>): mapping values are not allowed in this context at line 6 column 19 
from /home/kentos/.rvm/rubies/ruby-1.9.3-p374/lib/ruby/1.9.1/psych.rb:203:in `parse' 
from /home/kentos/.rvm/rubies/ruby-1.9.3-p374/lib/ruby/1.9.1/psych.rb:203:in `parse_stream' 
from /home/kentos/.rvm/rubies/ruby-1.9.3-p374/lib/ruby/1.9.1/psych.rb:151:in `parse' 
from /home/kentos/.rvm/rubies/ruby-1.9.3-p374/lib/ruby/1.9.1/psych.rb:127:in `load' 
from (irb):83:in `valid_yaml_string?' 
from (irb):89 
from /home/kentos/.rvm/rubies/ruby-1.9.3-p374/bin/irb:12:in `<main>' 

回答

7

使用你的代码的清理后的版本:

require 'yaml' 
require 'open-uri' 

URL = "https://github.com/TheNotary/the_notarys_linux_mint_postinstall_configuration" 

def valid_yaml_string?(yaml) 
    !!YAML.load(yaml) 
rescue Exception => e 
    STDERR.puts e.message 
    return false 
end 

puts valid_yaml_string?(open(URL).read) 

我得到:

(<unknown>): mapping values are not allowed in this context at line 6 column 19 
false 

当我运行它。

的原因是,你是从URL获取数据不是在所有YAML,这是HTML:

open('https://github.com/TheNotary/the_notarys_linux_mint_postinstall_configuration').read[0, 100] 
=> " \n\n\n<!DOCTYPE html>\n<html>\n <head prefix=\"og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog:" 

如果你只想要一个真/假响应是否是可解析YAML,删除此行:

STDERR.puts e.message 

不幸的是,超越这一点,并确定如果字符串是一个YAML字符串变得更加困难。你可以做一些嗅探,寻找一些线索:

yaml[/^---/m] 

将搜索YAML“文件”的标记,但YAML文件没有使用这些,也没有必须在开始文件。我们可以添加在收紧测试:

!!YAML.load(yaml) && !!yaml[/^---/m] 

但是,即使是留下了一些漏洞,在测试因此增加,看看有什么解析器回报可以帮助甚至更多。 YAML可以返回一个Fixnum,String,一个数组或一个哈希,但是如果您已经知道期望什么,您可以检查YAML想要返回的内容。例如:

YAML.load(({}).to_yaml).class 
=> Hash 
YAML.load(({}).to_yaml).instance_of?(Hash) 
=> true 

所以,你可以找一个哈希:

parsed_yaml = YAML.load(yaml) 
!!yaml[/^---/m] && parsed_yaml.instance_of(Hash) 

更换Hash与任何类型的,你认为你应该得到的。

有可能有更好的方法来嗅探出来,但这些都是我首先想要的。

+0

'!!'是什么意思? – fotanus 2013-05-02 01:51:42

+0

在IRB中尝试'!true',然后尝试'!! true',然后尝试'!('foo'=='foo')',后面跟着!!('foo'=='foo')'。 – 2013-05-02 01:53:02

+0

对不起,不知道我在想什么... – fotanus 2013-05-02 01:56:19

相关问题