Ruby getting deeply nested JSON API data - ruby-on-rails

I have a rails app which gets a response from World Weather Online API. I'm using the rest-client gem and the response is in JSON format.
I parse the response using:
parsed_response = JSON.parse(response)
Where parsed_response is obviously a hash.
The data I need are strings inside a hash inside an array inside a hash inside another array inside another hash inside another hash.
The inner-most nested hashes are inside ["hourly"], an array of 8 hashes, each with 20 keys, possessing string values of various weather parameters. Each of these hashes in the array is a different time of day (the forecast is three-hourly, 3*8 = 24hours).
So, for example, if I want the swell height in metres at 9pm, I find it with the following call:
#swell_height = parsed_data["data"]["weather"][0]["hourly"][7]["swellHeight_m"]
Where the 7th element in the array correspond to "time" => "2100"
While I can definitely work with this, I'm curious as to whether there is a more straightforward method of accessing my data, like if it was a database table, I could use active record, something like:
#swell_height = parsed_data.swellHeight_m.where(:time => "2100")

You may want to look at JSONPath. It does exactly what you need. Its syntax is very similar to XPath, but JSONPath works with JSON data (as obvious).
There is a Ruby implementation: https://github.com/joshbuddy/jsonpath
I personally use it in every project where I need to test JSON responses.

Related

Parse Hash in Ruby

How can I parse a hash in ROR?
I have a hash in string format(enclosed by double quotes) and i need to parse them to a valid hash.
eg.
input_hash = "{"name" => "john"}"
desired
output_hash = {"name" => "john"}
This is the wrong approach. String representation of a ruby hash is not a good way to serialise data. It is well structured, and definitely possible to get it back to a ruby hash (eval), but it's extremely dangerous and can give an attacker who has control over the input string full control over your system.
Approach the problem from a different angle. Look for where the string gets stored and change the code there instead. Store it for example as JSON. Then it can easily and safely be parsed back to a hash and can also be sent to systems running on something that is not ruby.

Ruby On Rails: Convert PostgreSQL JSON to usual JSON

I have a JSON field in my PostgreSQL database. If I do #profile.json, then I will get something like:
{ {"name"=>"jhon", "degree"=>"12312"}, "1480103144467"=>{"name"=>"", "degree"=>""}}`
It has all the => and other symbols, which I can not parse. How can I convert to normal format?
If you've declared your column of type json that's a signal to Rails to automatically serialize and decode your column on-demand, transparently. What you're seeing here is a traditional Ruby Hash structure, which is to be expected.
Inside the database itself it's stored as JSON.
If you need to re-emit this as JSON for whatever reason, like for an API, try this:
#profile.json.to_json
Calling your column something other than json is probably advisable, too.

Saving data from a JSON response

I currently have a JSON response, fairly simple one. But I couldn't find a good guide or kicking off point for getting the JSON response and saving it within a model that I have e.g posts.
"Grab a JSON feed containing posts and save each one within the posts
table in rails"
Is there a simple way to do this with rails?
Any help is greatly appreciated.
Not a lot to work with...but let's assume the json string is represented by the variable json_str.
parsed = JSON.parse(json_str)
The parsed string should now essentially just be key value pairs like any other hash. To get the value, simply use the key.
parsed["some_key"]
Will return the value. To make your post from this, you can take the values you need and pass them in one by one, like so:
Post.create(some_value: parsed["some_key"], # etc)
Or, if all of your keys happen to share names with your attributes, you can pass the params all at once by saying:
post = Post.new(parsed)
and then calling:
post.save
Let me know if you have trouble.

Iterate to every element of the multidimension array in ruby

I have a array i getting through an xml .i want to iterate every element to the array which is hash and get the every hash element value using key.
I want to someting like this>>
array>>
education_split = [{"University"=>"Institute Of Engineering And Emerging Technologies", "Degree"=>"MBA", "Year"=>"2007"}, {"University"=>"H.N.B. Garhwal University", "Degree"=>"MSC", "Year"=>"2005"}, {"University"=>"H.P. University", "Degree"=>"Med", "Year"=>"2003"}, {"University"=>nil, "Degree"=>"12th", "Year"=>"1999"}, {"University"=>nil, "Degree"=>"10th", "Year"=>nil}]
now i want to iterate to every element of the array and get the value of university ,degree,year in iteration. something like that..
education_split.each do |edu|
//here are some other things also like creating object
edu["University"]
edu ["Degree"]
edu["Year"]
end
This is also working but in some cases it is though error >> TypeError (no implicit conversion of String into Integer)
here all fields are string and values i am getting are also string.
Just need to check a hash :
education_split.each do |edu|
//here are some other things also like creating object
if edu.is_a? Hash
edu["University"]
edu ["Degree"]
edu["Year"]
end
end
Reading the error, I am sure your collection education_split contains also arrays with hashes. Now to prevent the error and as you interested only to hash that part of the code, just do a check if edu in any particular iteration, is a hash or not. if hash, do your operation or skip it.
TypeError (no implicit conversion of String into Integer) only comes, when you would try to get array elements using strings, instead of integers. Like a = [1, 2], and now do a['x'], and see you would get the exact error you are now getting.

jRuby hash iteration newbie here

I am very new to rails in general and what I have is a hash being passed as json for one format and now I need to pass it to the view to work with but I have no idea how to iterate over the hash to make it work in the view as I need to do some type of each loop over it. Its a 2 dimensional hash dunno if that means anything or not.
edit
example
{"status":"successful","service_list":[{"service_name":"mySQL","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"PHP","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"APache","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"Jetty","status":"RUNNING","status_message":"No errors reported","host":"1"}]}
This renders fine when I do it as JSON, but using the same thing to render it out in an HTML based view is where I am getting stuck
You have converted a Ruby has to a JSON hash, which is a Javascript format. In Ruby you would access a hash as follows:
hash = {"foo": "bar"}
puts hash["foo"] # This returns "bar"
JSON is similar to Ruby, and can be accessed in the same manner:
var hash = {"foo": "bar"};
alert(hash["foo"]); # This alerts "bar"
If you want to iterate through this collection in Javascript, you can use a for loop:
var data = {"status":"successful","service_list":[{"service_name":"mySQL","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"PHP","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"APache","status":"RUNNING","status_message":"No errors reported","host":"1"},{"service_name":"Jetty","status":"RUNNING","status_message":"No errors reported","host":"1"}]};
for(x=0;x<data["service_list"].length;x++) {
alert(data["service_list"][x]["service_name"]); # This returns "mySQL", ...
};
If you are wanting to convert this JSON object to a Ruby has you can call "JSON.parse" with your JSON string as an argument.

Resources