I have a problem with ruby and json.
I have a json-file with information scraped from the internet. For the following problem I’ll use a hardcoded file, which has the following syntax:
[{
"day": "20120827_234558",
"entries": [
{
"rank": "3",
"club": "SuS Schalke 1896 e.V.",
"votes": "126"
},
{
"rank": "4",
"club": "TuS Hamborn-Neumühl 07 e.V.",
"votes": "120"
}
]
},{
"day": "20120827_234700",
"entries": [
{
"rank": "1",
"club": "TLV Germania 1901 Essen-Überruhr",
"votes": "210"
},
{
"rank": "2",
"club": "Rumelner TV",
"votes": "141"
}
]
}]
I wrote then a ruby script which loads the json from the file and puts it into a hash,
fetches some information from the internet (as well hard coded in this example), adds these new information to the hash, converts the hash to json and stores it in the file again.
require 'rubygems'
require 'open-uri'
require 'json'
fname = 'ranking.json'
json = JSON.load(File.open(fname))
json.each do |ranking|
puts 'entry:'
puts ranking['day']
end
puts "\n";
new_data = Array.new
new_data = { "day" => "20120828_234558", "entries" => "sgankhask" }
json << new_data.to_json
json.each do |ranking|
puts 'entry:'
puts ranking['day']
end
So it’s all about simply appending data in json format to an already existing json.
But if I execute this script, I get the following output:
entry:
20120827_234558
entry:
20120827_234700
entry:
20120827_234558
entry:
20120827_234700
entry:
day
I’m confused about the last row. I assumed the last row to be entry: 20120828_234558.
It seems, that Ruby takes the key (‘day’) of the hash instead of the value (‘20120828_234558’)?
What is wrong in my script? Any help is appreciated.
JSON is a string format for representing data structures. In Ruby, those data structures are represented with hashes (sometimes called dictionaries or maps) and arrays and so forth.
The last item you add, new_data, you invoke
to_jsonon it first, turning it into a string in the JSON format. So your data looks like this:See how the last item is actually a string, not a hash? So when you say
ranking['day'], it is not asking a hash for its key'day', but rather asking the string for the substring'day', which is why it prints the wrong value.Generally, when you’re confused about data like this, you can use the
pmethod.putswill output things as they would be read by humans, butpprints them in a way that represents them as data. For instance, I figured this out by addingp jsonbefore the loop that printed them.So when do you use JSON? When you’re ready to serialize your data back to the file.
Also note, that it would be better to do
json = JSON.load(File.read fname)because you’ve opened the file, but never closed it (plus it’s cleaner to look at).Also,
new_data = Array.newdoesn’t actually do anything since you set it to a hash on the next line.