【问题标题】:Parse a string as if it were a querystring in Ruby on Rails将字符串解析为 Ruby on Rails 中的查询字符串
【发布时间】:2022-02-07 18:16:32
【问题描述】:

我有一个这样的字符串:

"foo=bar&bar=foo&hello=hi"

Ruby on Rails 是否提供方法来解析它,就好像它是一个查询字符串,所以我得到一个像这样的哈希:

{
    :foo => "bar",
    :bar => "foo",
    :hello => "hi"
}

还是我自己写?

编辑

请注意,上面的字符串不是来自 URL 的真正查询字符串,而是存储在 Facebook Connect 的 cookie 中的字符串。

【问题讨论】:

    标签: ruby-on-rails parsing query-string


    【解决方案1】:

    答案取决于您使用的 Rails 版本。如果您使用的是 2.3 或更高版本,请使用 Rack 的内置解析器解析参数

     Rack::Utils.parse_nested_query("a=2") #=> {"a" => "2"}
    

    如果您使用的是旧版 Rails,您确实可以使用 CGI::parse。请注意,模块之间对哈希和数组的处理方式存在细微差别,因此您需要验证您获得的数据是否适合您选择的方法。

    您还可以将Rack::Utils 包含在您的类中以进行速记访问。

    【讨论】:

    • 如果你想得到一个像 rails 为你提供的 params 对象,你可以这样做: params = ActionController::Parameters.new(Rack::Utils.parse_nested_query("a=2"))
    • 有谁知道是否可以避免将查询字符串参数值转换为字符串?例如我想要这种行为:``` Rack::Utils.raw_parse_nested_query("a=2") #=> {"a" => 2} ```
    • 虽然这在大多数情况下都很好:它将"a[]=&a[]=z" 解析为{"a[]"=>["", "z"]},而ActionController::Base 实际使用的任何解析器都会返回{:a => ["z"]}
    【解决方案2】:

    CGI::parse("foo=bar&bar=foo&hello=hi")
    

    给你

    {"foo"=>["bar"], "hello"=>["hi"], "bar"=>["foo"]}
    

    编辑: 正如Ryan Long 所指定的,这个版本考虑了同一个键的多个值,如果你也想解析数组,这很有用。

    编辑 2:

    正如Ben 指出的那样,当数组使用ruby on rails 样式数组表示法格式化时,这可能无法很好地处理数组。 rails 样式数组表示法是:foo[]=bar&foo[]=nopJulik's response 确实可以正确处理这种风格。

    如果您有foo=bar&foo=nop 之类的参数,此版本只会正确解析数组。

    【讨论】:

    • 这是我尝试过的唯一处理每个参数的多个实例的实现——谢谢!
    • 问题是大多数人不想要数组并且期望一个简单的键=>值响应
    • @julik 的回答应该被接受。 CGI::parse 没有正确处理数组
    【解决方案3】:

    编辑:正如 cmets 中所说,如果有人想伤害你,象征化键可以让你的服务器停机。我在开发低配置应用程序时仍然经常这样做,因为它使事情变得更容易使用,但我不会再为高风险应用程序这样做了

    不要忘记符号化获得你想要的结果的键

    Rack::Utils.parse_nested_query("a=2&b=tralalala").deep_symbolize_keys
    

    此操作对重复项具有破坏性。

    【讨论】:

    • 符号化用户提供的密钥是个坏主意。符号不会 GC,因此如果有人使用大量虚假参数键向您的服务器发送垃圾邮件,它会在某个时候耗尽进程内存。
    • Ruby 2.2 现在将 GC 符号。
    【解决方案4】:

    如果您谈论的是用于获取有关参数数据的 Url

    > request.url
    => "http://localhost:3000/restaurants/lokesh-dhaba?data=some&more=thisIsMore"
    

    然后获取查询参数。使用

    > request.query_parameters
    => {"data"=>"some", "more"=>"thisIsMore"}
    

    【讨论】:

      【解决方案5】:

      如果你想要一个哈希,你可以使用

      Hash[CGI::parse(x).map{|k,v| [k, v.first]}]
      

      【讨论】:

      • CGI.parse(query).transform_values(&:first)
      猜你喜欢
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 2014-06-21
      相关资源
      最近更新 更多