简体   繁体   中英

Problems querying JSON nested hash response in Ruby

Cannot seem to solve this problem:

I'm getting JSON nested hash responses from Lastfm and everything works fine when the response is structures as such:

{"topalbums" =>{"album" =>{"name =>"Friday Night in Dixie"}}}

However if the artist does not have a top album the response is structured this way and I get a NoMethodError undefined method '[]' for nil:NilClass.

{"topalbums" =>{"#text"=>"\n   ", "artist"=>"Mark Chestnutt"}}

What I want to do is query the response so I do not keep getting this error.

Here is my method:

 def get_albums
   @albums = Array.new
   @artistname.each do |name|
      s = LastFM::Artist.get_top_albums(:artist => name, :limit => 1)
      r = JSON.parse(s.to_json)['topalbums']['album']['name']
      @albums.push(r)
   end
 end

which gives me exactly what I want if the artist has a top album, what I need to do is somehow add a condition to query the keys in the nested hash. However, I cannot seem to grasp how to do this as when I add this line of code to check key values:

s.each_key { |key, value| puts "#{key} is #{value}" } 

the output I get is this:

topalbums is

so topalbums key does not have a value associated with it.

This is what I have tried so far:

  def get_albums
   @albums = Array.new
   @artistname.each do |name|
      s = LastFM::Artist.get_top_albums(:artist => name, :limit => 1)
      if s.has_key?('album') #I know this won't work but how can I query this?
         r = JSON.parse(s.to_json)['topalbums']['album']['name']
         @albums.push r 
      else
         @albums.push(name << "does not have a top album")
      end
   end
 end

How can I fix this so I get 'Mark Chestnut does not have a top album' instead of the NoMethodError ? Cheers

Use Hash#fetch default values, I would do as below:

No "album" key present

hash = {"topalbums" =>{"#text"=>"\n   ", "artist"=>"Mark Chestnutt"}}
default_album = {"name" => "does not have a top album"}
hash["topalbums"].fetch("album", default_album)["name"]
#=> "does not have a top album"

"album" key present

hash = {"topalbums" =>{"#text"=>"\n   ", "artist"=>"Mark Chestnutt", "album" => {"name" => "Foo"}}}
hash["topalbums"].fetch("album", default_album)["name"]
#=> "Foo"

So if the hash does not have an "album" key fetch defaults to default_album else it uses the key it find as in the second case

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM