有时在处理API响应时,我最终会写出类似的内容:
what_i_need = response["key"]["another key"]["another key 2"]
问题是,如果缺少"another key"
,它会抛出错误。我不喜欢那样。如果what_i_need
出现nil
,如果整个过程中出现问题,我会更开心。
是否有比以下更优雅的解决方案:
what_i_need = nil
begin
what_i_need = response["key"]["another key"]["another key 2"]
rescue Exception => e
end
我还考虑过猴子修补NilClass你试图访问nil["something"]
它会返回nil
,但我不确定这是否是最好的方法,如果有可能的话。
答案 0 :(得分:9)
使用Hash#fetch默认值。
h = {:a => 2}
h.fetch(:b,"not present")
# => "not present"
h.fetch(:a,"not present")
# => 2
没有默认值,它会抛出KeyError
。
h = {:a => 2}
h.fetch(:b)
# ~> -:2:in `fetch': key not found: :b (KeyError)
但是你可以使用嵌套的Hash
,你可以使用:
h = {:a => {:b => 3}}
val = h[:a][:b] rescue nil # => 3
val = h[:a][:c] rescue nil # => nil
val = h[:c][:b] rescue nil # => nil
答案 1 :(得分:6)
Ruby 2.0有NilClass#to_h
。
what_i_need = response["key"].to_h["another key"].to_h["another key 2"]
答案 2 :(得分:2)
从Objective-C的键值编码系统中汲取灵感,您可以使用轻量级DSL在一个任意嵌套的数据结构中移动一系列键:
module KeyValue
class << self
def lookup(obj, *path)
path.inject(obj, &:[]) rescue nil
end
end
end
h = { a: { b: { c: 42, d: [ 1, 2 ] } }, e: "test"}
KeyValue.lookup(h, :a, :b, :d, 1) # => 2
KeyValue.lookup(h, :a, :x) # => nil
或者,如果你只想要一个班轮:
(["key", "another key", "another key 2"].inject(h, &:[]) rescue nil)
答案 3 :(得分:1)
要稍微扩展@Priti’s answer,您可以使用Hash#fetch
链代替Hash#[]
来返回空哈希,直到您到达链中的最后一个,然后返回{ {1}}:
nil
或依赖于引发的KeyError异常(可能不是最好的,因为应该避免控制流的异常):
what_i_need = response.fetch('key', {})
.fetch('another key', {})
.fetch('another key 2', nil)