【问题标题】:Why do I get NoMethodError when using variables to access elements of a Ruby hash parsed from JSON?为什么在使用变量访问从 JSON 解析的 Ruby 哈希元素时会出现 NoMethodError?
【发布时间】:2016-05-24 00:09:48
【问题描述】:

我正在尝试使用使用 JSON gem 的 Ruby 脚本解析示例 JSON 文件。这是我要解析的文件:

{
  "page": {
    "title": "Templating Example"
  },
  "teacher": {
    "name": "Mr. Bill"
  },
  "students": [
    { "name": "Bruce Wayne", "nicknames": ["Batman"] },
    { "name": "Peter Parker", "nicknames": ["Spidey", "Spiderman", "Spider-Man"] }
  ]
}

我可以使用以下脚本从这个 JSON 中提取数据:

require 'json'
file = File.read("data.json")
        response = JSON.parse(file)
        page_title = response["page"]["title"]

在上述情况下,page_title 返回“模板示例”

当我尝试将变量放入“页面”和“标题”位置时,我遇到的麻烦是:

var1 = "page"
var2 = "title"
page_title = response["var1"]["var2"]

我尝试了各种使用引号和不使用引号的解决方案,转义引号,传递已经格式化为括号和引号的变量,但我总是收到错误:

undefined method `[]' for nil:NilClass (NoMethodError)

`undefined method `response' for main:Object (NoMethodError)

【问题讨论】:

  • 这些错误是在哪里/由什么引发的?
  • 你打算做什么?您是否尝试为页面标题分配一个值并操作原始数据?您是否尝试访问该数据的其他部分?
  • 欢迎来到 Stack Overflow。没有必要,也不是特别希望有诸如“谢谢”或“任何建议将不胜感激”之类的东西。 Stack Overflow 问题和答案包含一本在线参考书,类似于一本食谱。问候、告别和签名不是问答的可取部分。

标签: ruby json parsing hash key


【解决方案1】:

您似乎正在尝试将 [] 与您的 JSON 中不存在的键(方法参数)一起使用。例如:

hash = { foo: 1, bar: 2 }
hash[:foo] #this key exists in hash
#=> 1
hash[:some_var] #this key not exists
#=> nil
hash[:some_var][:var2] #call [] method on nil class
#=>undefined method `[]' for nil:NilClass (NoMethodError)

如果您想在 response 哈希中添加一个值,请这样写:

response[:var1] = {}
response[:var1][:var2] = your_value

或者:

response[:var1] = { var2: your_value } 

或者问题在这里:

response["#{var1}"]["#{var2}"]

response[var1][var2]

【讨论】:

  • 非常感谢。我刚刚在我的原始查询中添加了一个说明。 var1 和 var2 代表的值是“page”和“title”(在这种情况下),但我无法以这种方式替换它们。我实际上正在编写一个循环,因此需要能够在哈希中使用变量。
  • 已编辑。试试response[var1][var2]
  • 永远不要"#{var1}"。如果您知道 var1 是一个字符串,只需直接使用它(如上一个示例所示)。如果您不确定它是一个字符串并且您需要它是一个字符串,只需执行var1.to_s
  • 完全同意你的看法。这只是 hash["prefix_#{var}"] 之类的实例。
【解决方案2】:

应该是

var1 = "page"
var2 = "title"
page_title = response[var1][var2]

否则var1 将被评估为内容为var1 的字符串,而不是“var1 的内容”。

【讨论】:

    【解决方案3】:

    问题:缺少哈希键

    page_title = response["var1"]["var2"]

    这些键不​​是变量,它们是字符串。您发布的哈希中不存在您引用的字符串键。使用您当前的代码,您需要:

    { 'var1' => {'var2' => :foo} }
    

    存在(或合并到)您的哈希中以使其正常工作。否则,如果 'var1' 键不存在,则无法在其上调用 [] 方法而不引发 NoMethodError 异常。

    您可以通过使用变量作为键来解决这个问题,或者通过如下所述的其他方式来解决这个问题。

    可能的解决方案

    您有多种选择,具体取决于您真正想做的事情:

    1. 对于 Ruby 2.3.0 或更高版本,使用 Hash#dig 以避免在尝试获取嵌套值时出现异常。例如:

      response.dig 'page', 'title'
      #=> "Templating Example"
      
      response.dig 'var1', 'var2'
      #=> nil
      

      如果返回值为 nil,你显然仍然需要决定要做什么,但至少你不会得到意外的异常。

    2. 使用实际变量而不是字符串来表示您的哈希键。例如:

      var1 = 'page'
      var2 = 'title'
      
      response[var1][var2]
      #=> "Templating Example"
      
    3. 在执行操作之前,将另一个散列合并到响应散列(例如,使用 Hash#merge!)。例如:

      var_hash = { 'var1' => {'var2' => :foo} }
      response.merge! var_hash
      response['var1']['var2']
      #=> :foo
      

    这些解决方案中的任何一个或它们的组合都可以帮助您解决问题。最适合您的方法会因您的具体用例而异。

    【讨论】:

    • 非常有用的cmets。非常感谢。解决方案 2 对我有用。
    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 2011-11-24
    相关资源
    最近更新 更多