在Ruby中使用JSON属性访问器

时间:2015-12-06 22:38:30

标签: ruby-on-rails ruby json

我正在使用返回

的JSON文件
"Rows": [
   {
      "Id": "Row1",
      "Dataset": "Person",
      "ColumnFields": [
        "John",
        "attr.0.PYNM",
        "attr.1.PYUV",
        "attr.2.PHGT"
   }
    ]

一旦我将JSON解析为哈希,我如何使用密钥attr.0.PYNM来访问从API响应返回的哈希? API响应类似于

{
 attr:
  [
    {
     'PYNM' => 'value1'
    },
    {
     'PYUV' => 'value2'
    }
 ]
}

response['attr'][0]['PYNM']这样的东西?如果值返回nil或空字符串,我还需要使用fetch来定义默认值。

3 个答案:

答案 0 :(得分:0)

"attr.0.PYNM"是String类型的值,而不是键。 ColumnFields 是一个数组,其内容只能通过索引访问(或使用Array.each)。

访问它的方式:

hash['Rows'][0]['ColumnFields'][1] // For "attr.0.PYNM"

答案 1 :(得分:0)

你是对的。如果您的回答是这样的:

{
 attr:
  [
    {
     'PYNM' => 'value1'
    },
    {
     'PYUV' => 'value2'
    }
 ]
}

您需要执行以下操作

response[:attr][0]['PYNM']

(注意attr作为符号而不是字符串)。希望它可以帮到你。

答案 2 :(得分:0)

这就是Enumerable#reduce真正有用的东西:

data = {
  "attr" => [
    { 'PYNM' => 'value1' },
    { 'PYUV' => 'value2' }
  ]
}

def dig(data, key)
  key.split('.').reduce(data) do |current, key_part|
    break if current.nil?
    key_part = Integer(key_part) if current.is_a?(Array)
    current[key_part]
  end
end

p dig(data, "attr.0.PYNM")
# => "value1"

p dig(data, "attr.1")
# => { "PYUV" => "value2" }

p dig(data, "attr.0.QWERTYUIOP")
# => nil

p dig(data, "attr.1.2")
# => nil

p dig(data, "attr.foo")
# => prog.rb:10:in `Integer': invalid value for Integer(): "foo" (ArgumentError)

请注意,在输入中我使用了字符串键("attr"而不是:attr)。如果您的输入同时包含字符串和符号键,则可能必须扩充代码 - 或者,如果您使用的是Rails,则可能是HashWithIndifferentAccess,它可能(或可能不)避免此问题。

另请注意,我使用Kernel#Integer代替String#to_i来更严格地转换数组键。 to_i会将"foo"转换为0,这会产生错误的结果,因此最好使用Integer来引发错误。

但仍有一些案例未涵盖,例如, ".foo""foo..bar"""