tshckr tshckr - 2 months ago 8
JSON Question

Rails how to display hash from JSON request

I'm trying to display the inner levels of the hash from my JSON request.

This is the return from JSON request:

{
"results": [
{
"utc_offset": -25200000,
"venue": {
"zip": "94305",
"country": "us",
"localized_country_name": "USA",
"city": "Stanford",
"address_1": "750 Escondido Road",
"name": "Ray's - Graduate Community Center",
"lon": -122.158386,
"id": 5612552,
"state": "CA",
"lat": 37.423393,
"repinned": false
},
"status": "upcoming"
},
{
"utc_offset": -25200000,
"venue": {
"zip": "94306",
"country": "us",
"localized_country_name": "USA",
"city": "Palo Alto",
"address_1": "25 Churchill Ave",
"name": "Palo Alto High School",
"lon": -122.154121,
"id": 1566333,
"state": "CA",
"lat": 37.433186,
"repinned": false
},
"status": "upcoming"
},
{
"utc_offset": -25200000,
"venue": {
"zip": "94306",
"country": "us",
"localized_country_name": "USA",
"city": "Palo Alto",
"address_1": "25 Churchill Ave",
"name": "Palo Alto High School",
"lon": -122.154121,
"id": 1566333,
"state": "CA",
"lat": 37.433186,
"repinned": false
},
"status": "upcoming"
}
]
}
}


I've referred to: How to use JSON data returned by API call in Rails 4, How to get a second level field from json file using ruby, Why do I get "no implicit conversion of String into Integer (TypeError)"?, How to access JSON in Rails?

Which helped me get to this point, I can display the inner levels of the hash if I specify the array index using
@result = @api_response["results"][0]["venue"]["name"]
which returns
"Ray's - Graduate Community Center"
. This is what I am trying to display, but I wanted to display the name for all the venue on the list and not just the name at index [0]. But I'm not sure how to iterate through the index.

I can also display the hashed results by using
@result = @api_response["results"]
and iterate through using:

<% @result.each do |i| %>
<%= i["venue"] %>
<% end %>


Which returns:

{"zip"=>"94305", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Stanford", "address_1"=>"750 Escondido Road", "name"=>"Ray's - Graduate Community Center", "lon"=>-122.158386, "id"=>5612552, "state"=>"CA", "lat"=>37.423393, "repinned"=>false}
{"zip"=>"94305", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Stanford", "address_1"=>"750 Escondido Road", "name"=>"Ray's - Graduate Community Center", "lon"=>-122.158386, "id"=>5612552, "state"=>"CA", "lat"=>37.423393, "repinned"=>false}
{"zip"=>"94306", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Palo Alto", "address_1"=>"25 Churchill Ave", "name"=>"Palo Alto High School", "lon"=>-122.154121, "id"=>1566333, "state"=>"CA", "lat"=>37.433186, "repinned"=>false}
{"zip"=>"94306", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Palo Alto", "address_1"=>"25 Churchill Ave", "name"=>"Palo Alto High School", "lon"=>-122.154121, "id"=>1566333, "state"=>"CA", "lat"=>37.433186, "repinned"=>false}

{"zip"=>"94306", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Palo Alto", "address_1"=>"25 Churchill Ave", "name"=>"Palo Alto High School", "lon"=>-122.154121, "id"=>1566333, "state"=>"CA", "lat"=>37.433186, "repinned"=>false}
{"zip"=>"94306", "country"=>"us", "localized_country_name"=>"USA", "city"=>"Palo Alto", "address_1"=>"25 Churchill Ave", "name"=>"Palo Alto High School", "lon"=>-122.154121, "id"=>1566333, "state"=>"CA", "lat"=>37.433186, "repinned"=>false}


But when I try using this:

<% @result.each do |i| %>
<%= i["venue"]["name"] %> <br />
<% end %>


I get a
undefined method
[]' for nil:NilClass` error, it does not let me access the "name" inside of "venue" which I am trying to display.

Am I on the right track? Is there a better way to display the inner levels of the hash? Any feedback would help. Thanks!

Answer

Looks like you are on the right track; it's just that there's a result in there that is either nil or that doesn't have a venue within it.

How you approach the problem depends on what you want to do those situations.

You could filter the results to exclude results without a venue. It would be more efficient to do this as part of your query but you could just do:

@result.select { |r| r.present? && r.has_key?('venue') }.each do |i|

Alternatively you could output "no venue" or somesuch if the venue is missing. I tend to use fetch in situations like this. You can try to fetch the value from the hash but return a default if the key isn't in the hash. So, in your case, you could do:

<%= i.fetch('venue', {}).fetch('name', 'No venue') %>

This looks for the venue hash in the result but returns an empty hash if it isn't there. The second fetch then tries to retrieve the name from that hash and again returns 'No venue' if it couldn't find it.

Comments