How to select for an JSON element in Ruby - ruby-on-rails

I have a large amount of nested data formatted in JSON.
I would like to select for a single element:
{"data": [
{"id": "123456","from": {"name": "Jason Wade","id":
"654321"},"message":
"http://www.youtube.com/watch?v=ZfXHAqBRIEk"
...
How do I efficiently select for
a single element, say "message"?
Is there a simple recommended
method for this? Say convert it to
an array, or something?
Could you point me to some reading for
parsing JSON?
Thanks!

If you are using Rails, see the question in my comment. If you are using pure Ruby, there is a gem called json. Install the gem, and use like this
require 'rubygems'
require 'json'
url = "www.example.com/api?format=json"
response = Net::HTTP.get_response(URI.parse(url))
data = response.body
result = JSON.parse(data)
JSON format and ruby data types have similarity and in your example, the result will be a hash like this
{"data"=>[{"message"=>"http://www.youtube.com/watch?v=ZfXHAqBRIEk", "from"=>{"name"=>"Jason Wade", "id"=>"654321"}, "id"=>"123456"}]}

Related

Ruby : How to parse a jsonp and save json data to database

I want to parse the JSONP data and save that data into my data base .
I have my jsonp url lets say this >>http://a0.awsstatic.com/pricing/1/ec2/pricing-data-transfer-with-regions.min.js?callback=callback&_=1409722308446
Its not normal json object so how can i parse this json in ruby/ruby on rails and save the data into my database. I want to save the data in table having filed lets say region , name ,type, price .
What are the ways to do the same.
JSONP is a work around for the same origin policy in client side JavaScript. It isn't required for processing data in Ruby. Firstly I would try to find the data available in plain JSON, without the callback.
If, however, that URL is absolutely the only one you can call for this data, then I would strip away the callback using a regular expression and then parse the plain JSON data.
If you have already loaded the contents of that file into a variable called jsonp, then something like this might work:
require 'net/http'
require 'json'
uri = URI.parse('http://a0.awsstatic.com/pricing/1/ec2/rhel-od.min.js?callback=callback&_=1409731896563')
jsonp = Net::HTTP.get(uri)
jsonp.gsub!(/^.*callback\(/, '') # removes the comment and callback function from the start of the string
jsonp.gsub!(/\);$/, '') # removes the end of the callback function
jsonp.gsub!(/(\w+):/, '"\1":')
hash = JSON.parse(jsonp)
then hash will have the parsed JSON from the response.
Please note, this code has no error handling and should be treated as a starting point for your final solution.
[edit] Added the third gsub to change the JavaScript style keys to JSON style keys. This works in this case because the keys all appear to be simple enough to fit that regex.
[edit2] Added way to load the JSONP with Net::HTTP
If what you're really trying to do is parse the Amazon price list JS file into Ruby, there is a better (read: safer--no evals) way to do it:
require 'net/http'
require 'json'
JSON.parse(
Net::HTTP.get(
URI.parse('http://a0.awsstatic.com/pricing/1/ec2/rhel-od.min.js')
).split('callback(')[1].sub(');', '').gsub(/(\w+):/, '"\1":')
)
As the data is as a raw JS object form, it's actually valid Ruby:
require 'json'
data = '{key: "value", key2: 33}'
obj = eval data
obj[:key]
#=> "value"
obj.to_json
# => "{\"key\":\"value\",\"key2\":33}"
You must trust your source completely though - this would allow the running of abstract Ruby code if the data were tampered with - which could in turn run abstract command-line terminal code, using the back-tick operators. This could delete your hard drive for example.

Transforming JSON to nested ruby hash

I have a JSON block that I want to convert to a ruby hash.
json_blob = {"WHATEVER"=>{"FOO"=>"BAR", "CAT"=>"DAY}}
so that when I am using the data, I can check whether the data is there. Example:
hashed_json_blob[:whatever][:foo] returns "bar"
and also, I could handle values that don't exist either (they were omitted in the json_blob).
hashed_json_blob[:whatever][:nonexistant] returns nil
Note: if there is an easier way with the data as XML, that can work to. The json_blob was pulled using JSON.parse
your json_blob object is already a hash (minus one missing quote at the end of "DAY"):
json_blob = {"WHATEVER"=>{"FOO"=>"BAR", "CAT"=>"DAY"}}
with this you can do:
json_blob["WHATEVER"]
=> {"FOO"=>"BAR", "CAT"=>"DAY"}
json_blob["WHATEVER"]["FOO"]
=> "BAR"
The same data as a json object would look like this:
{"WHATEVER":{"FOO":"BAR","CAT":"DAY"}}
gem install json
require 'json'
json_blob = {"WHATEVER"=>{"FOO"=>"BAR", "CAT"=>"DAY}}
abc = JSON.parse(json_blob)
now you can perform operations on abc

Ruby getting deeply nested JSON API data

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.

How to save data received in json format to database?

i have an rubyonrails backend for an iphone application
the webservice receives data in json format
eg:
[
{"created_at":"2011-11-28T12:53:25Z","body":"good article","updated_at":"2011-11-23T12:53:30Z","id":1,"commenter":"shanib","user_id":1},
{"created_at":"2011-11-28T07:29:53Z","body":"dfasdf","updated_at":"2011-11-28T07:29:53Z","id":2,"commenter":"dasf","user_id":1},
{"created_at":"2011-11-28T08:36:37Z","body":"","updated_at":"2011-11-28T08:36:37Z","id":3,"commenter":"","user_id":1},
{"created_at":"2011-11-28T12:41:18Z","body":"qwewqe","updated_at":"2011-11-28T12:41:18Z","id":4,"commenter":"Allen","user_id":1}
]
How can i parse this json and save into database using looping
Can you provide any reference links or demo?
You can use the 'json' gem. (Which is now already installed together with rails 3.1.x).
For example:
json_data = '[
{"created_at":"2011-11-28T12:53:25Z","body":"good article","updated_at":"2011-11-23T12:53:30Z","id":1,"commenter":"shanib","user_id":1},
{"created_at":"2011-11-28T07:29:53Z","body":"dfasdf","updated_at":"2011-11-28T07:29:53Z","id":2,"commenter":"dasf","user_id":1},
{"created_at":"2011-11-28T08:36:37Z","body":"","updated_at":"2011-11-28T08:36:37Z","id":3,"commenter":"","user_id":1},
{"created_at":"2011-11-28T12:41:18Z","body":"qwewqe","updated_at":"2011-11-28T12:41:18Z","id":4,"commenter":"Allen","user_id":1}
]'
data = JSON.parse(data)
will give you a hash which you can iterate trough. (And you can access the values using like data[0]["created_at"]).

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