假设我从API中获取JSON嵌套哈希(或哈希数组)
@example = {"results" = > {{"poop" => "shoop"},{"foo" => {"shizz" => "fizz", "nizzle"=>"bizzle"}}}
上面嵌套哈希的YAML标记
- poop: shoop
- foo:
shizz: fizz
nizzle: bizzle
现在让我们从散列中使用ActiveRecord创建一个db条目。这很好。
Thing.create!(:poop => @example["results"]["poop"],
:shizz => @example["results"]["foo"]["shizz"],
:nizzle=> @example["results"]["foo"]["nizzle"])
但是,如果'foo'为空或为零怎么办?例如,如果API结果的“人”哈希带有“名字”,“姓氏”#等,那么“人” “如果没有数据,散列通常是空的,这意味着它内部的散列不存在。
@example = {"results" = > {{"poop" => "shoop"},{"foo" => nil }}
Thing.create!(:poop => @example["results"]["poop"],
:shizz => @example["results"]["foo"]["shizz"],
:nizzle=> @example["results"]["foo"]["nizzle"])
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
处理此问题的最佳方式是什么?
答案 0 :(得分:4)
我前来遇到nil
敏感的Hash#get
方法。
class Hash
def get(key, default=nil)
key.split(".").inject(self){|memo, key_part| memo[key_part] if memo.is_a?(Hash)} || default
end
end
h = { 'a' => { 'b' => { 'c' => 1 }}}
puts h.get "a.b.c" #=> 1
puts h.get "a.b.c.d" #=> nil
puts h.get "not.here" #=> nil
这种JSON钻孔非常方便。
否则你必须做这样的事情:
h['a'] && h['a']['b'] && h['a']['b']['c']
那太糟糕了。
答案 1 :(得分:2)
如果你正在使用rails(不确定它是否在ruby 1.9中):
h = {"a"=>1}
h.try(:[],"a") #1
h.try(:[],"b") #nil
h2 = {"c"=>{"d"=>1}}
h2.try(:[],"c").try(:[],"d") #1
h2.try(:[],"a").try(:[],"foo") #nil
# File activesupport/lib/active_support/core_ext/object/try.rb, line 28
def try(*a, &b)
if a.empty? && block_given?
yield self
else
__send__(*a, &b)
end
end
答案 2 :(得分:2)
我继续开始将所有哈希结果传递给Hashie Mash。这样他们的行为就像Ruby对象一样,像一个冠军一样回应nils!
答案 3 :(得分:1)
Ruby 2.3.0在Hash
和Array
上引入了a new method called dig
,完全解决了这个问题。
value = hash.dig(:a, :b)
如果在任何级别缺少密钥,则返回nil
。