Reputation: 707
I'm trying to read some JSON that I received from a REST API but I'm having some issues.
To get my JSON, I'm using Open::URI. I created my request like this:
require "open-uri"
require "json"
content = open("http://foo.bar/test.json").read
result = JSON.parse(content)
At this point my JSON is supposed to be parsed from a string, and so if I correctly understood, a hash containing my JSON is built assuming the JSON I received has a structure that looks like this:
{
"root":
{
"foos":
{
"1":
{
"title" : "zero",
"number" : 0
},
"2":
{
"title" : "twenty",
"number" : 20
},
...
}
}
}
I would like to iterate over each foos
and, for each of them, get the title and the number. I tried this:
content["root"]["foos"].each do |foo| puts foo.title + " " + foo.number end
But, as output, I got:
#<Enumerator:0x007fceb8b33718>
Where is/are my mistake(s)?
Thanks in advance,
Upvotes: 0
Views: 181
Reputation: 160551
I'd do it like this:
require 'json'
require 'pp'
hash = JSON.parse(
'{
"root": {
"foos": {
"1": {
"title": "zero",
"number": 0
},
"2": {
"title": "twenty",
"number": 20
}
}
}
}'
)
results = hash['root']['foos'].map{ |k, v|
[v['title'], v['number']]
}
pp results
After running it outputs an array of arrays:
[["zero", 0], ["twenty", 20]]
map
might behave a bit differently than you'd expect with a hash; It assigns each key/value of the hash as an array of two elements. The key is the first element, the value is the second. Because your structure is a hash of hashes of hashes of hashes, when iterating over hash['root']['foos']
the values for keys "1"
and "2"
are a hash, so you can access their values like you would a hash.
Back to your code:
hash["root"]["foos"].each do |foo|
puts foo.title + " " + foo.number
end
won't work. It doesn't return an enumerator at all, so that part of the question is inaccurate. What your code returns is:
undefined method `title' for ["1", {"title"=>"zero", "number"=>0}]:Array (NoMethodError)
Upvotes: 1
Reputation: 9025
Here's an option... Iterate over the keys inside of the foos
object.
json = JSON.parse(your_sample_json)
=> {"root"=>{"foos"=>{"1"=>{"title"=>"zero", "number"=>0}, "2"=>{"title"=>"twenty", "number"=>20}}}}
foos = json["root"]["foos"]
=> {"1"=>{"title"=>"zero", "number"=>0}, "2"=>{"title"=>"twenty", "number"=>20}}
foos.keys.each { |key| puts foos[key]["title"] }
zero
twenty
Also, if you have control over the JSON object you're parsing, you could make foos
an array instead of a bunch of numbered objects.
Upvotes: 1