2012-12-05 24 views
1

说我有红宝石:获得价值正确类型的查询字符串

str = "a=2&b=3.05&c=testing" 

我跑

require 'cgi' 
out = {} 
CGI::parse(str).each { |k,v| out[k] = v[0] } 

当我输出a,2是string,我希望它是一个Int

out['a'] // "2" (instead of int 2) 
out['b'] // "3.05" (instead of float 3.05) 

是否有任何方法来纠正查询字符串中的类型?

更新:

添加了这个方法来测试数字

def is_a_number?(s) 
    s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true 
end 

和解析

CGI::parse(url).each do |k,v| 
    val = v[0] 
    if is_a_number? val 
     val = val.include?('.') ? val.to_f : val.to_i 
    end 
    out[k] = val 
end 

似乎与基本示例工作期间。这有什么不安全的吗?

+1

你只得到字符串作为查询值。这是为了简化HTTP会话/查询/事务。想象一下,如果整数和实数的本地二进制表示从非异构系统中抛出,我们就会有乐趣。因此,由于您在连接的服务器端,因此您必须了解您应接收的值的类型。 –

回答

2

编辑:这工作

require 'cgi' 

str = "a=2&b=3.05&c=testing" 
out = {} 

def typecasted(str) 
    [str.to_i, str.to_f, str].find { |cast| cast.to_s == str } 
end 

CGI::parse(str).each do |key, val| 
    out[key] = typecasted val.first 
end 

p out 
# => {"a"=>2, "b"=>3.05, "c"=>"testing"} 
+0

你有没有测试过? 2错误,typecasted必须首先定义,然后我得到'typecasted':未定义的方法'to_i'为[“2”]:Array(NoMethodError) – peter

+0

我没有。编辑 – AJcodez

+0

+1有趣的发现使用,我结合我的技术 – peter

3

简短的答案是否定的,没有办法只是得到正确的类型。你可以编写你自己的解析器,试图根据正则表达式匹配猜测。这种处理的典型方式是基于每个参数的预期类型手动解析它们。您可以拨打to_ito_f等方法将它们转换为您想要的类型。

-1

我想不出你有输入字符串的方式,但如果你可以改变,要

str = "a=2&b=3.05&c='testing'" 

(注意单引号),你可以使用在每个EVAL功能值,让红宝石猜测类型。

+1

我不认为使用eval是一个不错的选择,如果他们知道你在使用eval,那么有人会聪明地滥用它。期待吉姆提出的类型更好;简单地避免零(例如使用-1)以确保它被正确解析,因为如果String#to_i不能将字符串转换为整数,则返回0。如果你需要,你可以使用正则表达式和“标志”来表示可能的类型,但绝对不是'eval'。 – omninonsense

1

如果你分析它,这样你不应该有问题

out = {} 
CGI::parse(str).each do |k, v| 
    v, v = (v = v.first), (v if v[/[a-zA-Z]/]) || [v.to_i, v.to_f].max 
    out.merge!(Hash[k, v]) 
end  

与AJcodez的技术相结合这使

out = {} 
CGI::parse(str).each do |k, v| 
    v, out[k] = (v = v.first), [v.to_i, v.to_f, v].find { |c| c.to_s == v } 
end 

或者作为一个班轮

Hash[*CGI::parse(str).map {|k, v| v = v.first; [k, [v.to_i, v.to_f, v].find { |c| c.to_s == v }]}.flatten] 

给出

{"a"=>2, "b"=>3.05, "c"=>"testing"} 
+0

作为上面提到的@starship,你可能不想使用'eval()'。我们在这里讨论来自网络的CGI参数。从安全的角度来看,这是非常危险的。 –

+0

你是对的@舰船,发表了一个更安全的版本 – peter