Ruby:在查询字符串中获取值的正确类型
说我有
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
似乎可以使用基本示例。 这有什么不安全的吗?
编辑:这是有效的
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"}
简短的回答是否定的,没有办法只是得到正确的类型。 您可以编写自己的解析器,尝试根据正则表达式匹配进行猜测。 处理它的典型方法是根据每个参数的预期类型手动解析它们。 您可以调用to_i
和to_f
之类的方法将它们转换为您想要的类型。
如果你像这样解析它,你应该没有问题
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
或者作为一个class轮
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"}
我想不出你有这个输入字符串的方法,但是你可以改变它
str = "a=2&b=3.05&c='testing'"
(注意单引号),你可以在每个值上使用eval函数,让ruby猜测类型。