How do I extract a value from a JSON response? - ruby

I am writing some tests in Ruby using RestClient. The test is working fine and the response is in JSON however when I parse the JSON and try to extract the values I am looking for I get an error saying IndexError: key not found
IMO, my code should work. The JSON is:
{"user":{"#xmlns":{"dvi":"http:\/\/xxxx","a":"http:\/\/xxxx","$":"http:\/\/xxxx"},"link":[{"#rel":"self","$":"http:\/\/xxxx"},{"#rel":"user","$":"http:\/\/xxxx"},{"#rel":"usage","$":"xxxx"},{"#rel":"repositories","$":"http:\/\/xxxx"},{"#rel":"shares","$":"http:\/\/xxxx"},{"#rel":"shareMemberships","$":"http:\/\/xxxx"}],"phone":{"$":"3518012343001"},"email":{"$":""},"firstName":{"$":"Jim"},"lastName":{"$":"Joe"},"uid":{"$":"91bc7a72bc724e5e9b53e688dd105ed4"},"accountName":{"$":"3518012343001"},"notificationMethod":{"$":"email sms"},"accountStatus":{"$":"Active"},"serviceLevel":{"$":"5"},"repositoryCount":{"$":"1"},"usage":{"allowed":{"$":"5368709120"},"total":{"$":"1024"}},"contactEmail":{"$":"jim#joe.com"}}}
and my code is:
result = jsonabove
jdoc = JSON.parse(result)
notificationMethod = jdoc.fetch("notificationMethod")
return notificationMethod

That's happening because the notificationMethod key isn't the first level key in your hash. After preparing theJSON#parse method, you have a hash with only one key called user. You should get the value by this key and then apply your notificationMethod key. It looks like this:
require 'json'
result = <<HERE
{"user":{"......"}}
HERE
jdoc = JSON.parse(result)
notificationMethod = jdoc.fetch("user").fetch("notificationMethod")
puts notificationMethod

Related

OLA Money API Hash Code Error

While integrating OLA Money API, when I hit url with all parameter am getting error
"Hash Code mismatched"
The main problem is when we send generated hash code through url, then last 2 characters of hash key == are changed into %3D%3D. Could you please give me solution of this.
Both Hash key are given below:
Generated Hash Key before URL-------------------------------------------------------------------------
eyJjb21tYW5kIjoiZGViaXQiLCJhY2Nlc3NUb2tlbiI6IjN1NDFwODJ1VDEiLCJ1bmlxdWVJZCI6IjEyMzQ1Nk9MNTY0Nzg4OSIsImNvbW1lbnRzIjoib2RldFgiLCJ1ZGYiOiI4dkJkZiIsImhhc2giOiJjODkzZTFjMWViZTQ1MTliMTUzOGE1NTEyNTUzMzRjNGRlNjZiNWRiNDQ4OWI1MTdlN2MxN2RhYzM4YWMwNTA3MGY1ZDQ3MDBiNjRlMTUyMTUyYzg5NWVlYzFhMDYyMGYzMTFlNzkyMDYzNzk5OThjZDQ2ZGE0ZDkxMzRiYzEzZSIsInJldHVyblVybCI6Imh0dHA6Ly93d3cucnVwbGVlZGV2bG9wbWVudC5jb20vc2VydmljZS93ZWJzZXJ2aWNlc192MDMvb2xhbW9uZXkvb2xhUmVzcG9uc2UucGhwIiwibm90aWZpY2F0aW9uVXJsIjoiaHR0cDovL3d3dy5ydXBsZWVkZXZsb3BtZW50LmNvbS9zZXJ2aWNlL3dlYnNlcnZpY2VzX3YwMy9vbGFtb25leS9vbGFOb3RpZnkucGhwIiwiYW1vdW50IjoxLCJjdXJyZW5jeSI6IklOUiIsImNvdXBvbkNvZGUiOiIifQ==
Generated Hash Key in URL--------------------------------------------------------------------------------
eyJjb21tYW5kIjoiZGViaXQiLCJhY2Nlc3NUb2tlbiI6IjN1NDFwODJ1VDEiLCJ1bmlxdWVJZCI6IjEyMzQ1Nk9MNTY0Nzg4OSIsImNvbW1lbnRzIjoib2RldFgiLCJ1ZGYiOiI4dkJkZiIsImhhc2giOiJjODkzZTFjMWViZTQ1MTliMTUzOGE1NTEyNTUzMzRjNGRlNjZiNWRiNDQ4OWI1MTdlN2MxN2RhYzM4YWMwNTA3MGY1ZDQ3MDBiNjRlMTUyMTUyYzg5NWVlYzFhMDYyMGYzMTFlNzkyMDYzNzk5OThjZDQ2ZGE0ZDkxMzRiYzEzZSIsInJldHVyblVybCI6Imh0dHA6Ly93d3cucnVwbGVlZGV2bG9wbWVudC5jb20vc2VydmljZS93ZWJzZXJ2aWNlc192MDMvb2xhbW9uZXkvb2xhUmVzcG9uc2UucGhwIiwibm90aWZpY2F0aW9uVXJsIjoiaHR0cDovL3d3dy5ydXBsZWVkZXZsb3BtZW50LmNvbS9zZXJ2aWNlL3dlYnNlcnZpY2VzX3YwMy9vbGFtb25leS9vbGFOb3RpZnkucGhwIiwiYW1vdW50IjoxLCJjdXJyZW5jeSI6IklOUiIsImNvdXBvbkNvZGUiOiIifQ%3D%3D
I look forward to solution from you,
Issue here is - one of the Hash is getting URL encoded. Easiest way is to URL decode both the strings and then match. Here:
require 'uri'
h1 = "eyJjb21tYW5kIjoiZGViaXQiLCJhY2Nlc3NUb2tlbiI6IjN1NDFwODJ1VDEiLCJ1bmlxdWVJZCI6IjEyMzQ1Nk9MNTY0Nzg4OSIsImNvbW1lbnRzIjoib2RldFgiLCJ1ZGYiOiI4dkJkZiIsImhhc2giOiJjODkzZTFjMWViZTQ1MTliMTUzOGE1NTEyNTUzMzRjNGRlNjZiNWRiNDQ4OWI1MTdlN2MxN2RhYzM4YWMwNTA3MGY1ZDQ3MDBiNjRlMTUyMTUyYzg5NWVlYzFhMDYyMGYzMTFlNzkyMDYzNzk5OThjZDQ2ZGE0ZDkxMzRiYzEzZSIsInJldHVyblVybCI6Imh0dHA6Ly93d3cucnVwbGVlZGV2bG9wbWVudC5jb20vc2VydmljZS93ZWJzZXJ2aWNlc192MDMvb2xhbW9uZXkvb2xhUmVzcG9uc2UucGhwIiwibm90aWZpY2F0aW9uVXJsIjoiaHR0cDovL3d3dy5ydXBsZWVkZXZsb3BtZW50LmNvbS9zZXJ2aWNlL3dlYnNlcnZpY2VzX3YwMy9vbGFtb25leS9vbGFOb3RpZnkucGhwIiwiYW1vdW50IjoxLCJjdXJyZW5jeSI6IklOUiIsImNvdXBvbkNvZGUiOiIifQ=="
h2 = "eyJjb21tYW5kIjoiZGViaXQiLCJhY2Nlc3NUb2tlbiI6IjN1NDFwODJ1VDEiLCJ1bmlxdWVJZCI6IjEyMzQ1Nk9MNTY0Nzg4OSIsImNvbW1lbnRzIjoib2RldFgiLCJ1ZGYiOiI4dkJkZiIsImhhc2giOiJjODkzZTFjMWViZTQ1MTliMTUzOGE1NTEyNTUzMzRjNGRlNjZiNWRiNDQ4OWI1MTdlN2MxN2RhYzM4YWMwNTA3MGY1ZDQ3MDBiNjRlMTUyMTUyYzg5NWVlYzFhMDYyMGYzMTFlNzkyMDYzNzk5OThjZDQ2ZGE0ZDkxMzRiYzEzZSIsInJldHVyblVybCI6Imh0dHA6Ly93d3cucnVwbGVlZGV2bG9wbWVudC5jb20vc2VydmljZS93ZWJzZXJ2aWNlc192MDMvb2xhbW9uZXkvb2xhUmVzcG9uc2UucGhwIiwibm90aWZpY2F0aW9uVXJsIjoiaHR0cDovL3d3dy5ydXBsZWVkZXZsb3BtZW50LmNvbS9zZXJ2aWNlL3dlYnNlcnZpY2VzX3YwMy9vbGFtb25leS9vbGFOb3RpZnkucGhwIiwiYW1vdW50IjoxLCJjdXJyZW5jeSI6IklOUiIsImNvdXBvbkNvZGUiOiIifQ%3D%3D"
h1 == h2
# => false
URI.unescape(h1) == URI.unescape(h2)
# => true

Ruby Sinatra and JSON objects from toodledo API 2.0

I have a small problem with receiving JSON objects. I'm using Ruby 1.9.3 and my goal is to receive my tasks from an API via RestClient and print them more or less pretty onto the page.
I created a route /test:
get '/test' do
json_ip_url = "http://api.toodledo.com/2/tasks/get.php?key=198196ae24792467eec09ac2191*****;modafter=1234567890;fields=folder,star,priority"
ip_details = RestClient.get(json_ip_url)
test = JSON.pretty_generate(ip_details) # => throws exception
end
The JSON#pretty_generate line throws an error, "only generation of JSON objects or arrays allowed". What am I doing wrong here?
Update:
I'am now able to output via pretty_generate, but what do I have to do, to get the elements of it. Here is the JSON Data, it seems to me its an Array with Objects inside of it?
[{"num":"18","total":"18"},{"id":"11980343","title":"Add some items to your todo list","modified":1391670256,"completed":0,"folder":"0","star":"0"},{"id":"11980345","title":"Visit the Settings section and configure your account","modified":1391670256,"completed":0,"folder":"0","star":"0"},{"id":"11980347","title":"Watch our tutorial videos in the Help section","modified":1391670256,"completed":0,"folder":"0","star":"1"},{"id":"12607789","title":"test","modified":1392285802,"completed":0,"folder":"0","star":"0"},{"id":"12636039","title":"My Task","modified":1392308705,"completed":0,"folder":"0","star":"0"},{"id":"12636041","title":"Another","modified":1392308705,"completed":0,"folder":"0","star":"1"},{"id":"12636143","title":"My Task","modified":1392308789,"completed":0,"folder":"0","star":"0"},{"id":"12636145","title":"Another","modified":1392308789,"completed":0,"folder":"0","star":"1"},{"id":"12636449","title":"My Task","modified":1392308950,"completed":0,"folder":"0","star":"0"},{"id":"12636451","title":"Another","modified":1392308950,"completed":0,"folder":"0","star":"1"},{"id":"12636621","title":"My Task","modified":1392309061,"completed":0,"folder":"0","star":"0"},{"id":"12636623","title":"Another","modified":1392309061,"completed":0,"folder":"0","star":"1"},{"id":"12636665","title":"My Task","modified":1392309085,"completed":0,"folder":"0","star":"0"},{"id":"12636667","title":"Another","modified":1392309085,"completed":0,"folder":"0","star":"1"},{"id":"12636733","title":"My Task","modified":1392309137,"completed":0,"folder":"0","star":"0"},{"id":"12636735","title":"Another","modified":1392309137,"completed":0,"folder":"0","star":"1"},{"id":"12637135","title":"My Task","modified":1392309501,"completed":0,"folder":"0","star":"0"},{"id":"12637137","title":"Another","modified":1392309501,"completed":0,"folder":"0","star":"1"}]
The Code I used for pretty_generate:
get '/save' do
jdata = params[:data]
response = RestClient.get 'http://api.toodledo.com/2/tasks/get.php?key=da21e24e2a00ba9d45008974aed00***;modafter=1234567890;fields=folder,star,priority', {:accept => :json}
test = JSON.parse(response)
test.to_json
output = JSON.pretty_generate(test)
puts output
RestClient#get returns the raw response as a string (and not a hash or array) when called without a block, so ip_details isn't a structure that JSON#pretty_generate knows how to handle. You need to use JSON#parse to turn the response into a hash or array first.

Issue on parsing string at JSON.parse

In controller side i am getting params like
"{\"violation_date\":\"sdfsdf\",\"violation_time\":\"\"},{\"violation_date\":\"sdfdsf\",\"violation_time\":\"sdfsdf\"},{\"violation_date\":\"1233\",\"violation_
time\":\"\"},{\"violation_date\":\"test\",\"violation_time\":\"time\"}"
class of this is String. I am trying to parse this. Through
JSON.parse(params_gotton)
Got
JSON::ParserError (757: unexpected token at ',{"violation_date":"sdfdsf","violation_time":"sdfsdf"},{"violation_date":"1233","violation_time":""},{"violation_d
te":"test","violation_time":"time"}'):
What i am doing wrong here. Any suggestions?
It's not valid json, this will work (use []):
require 'json'
jsn = '[{"violation_date":"sdfsdf","violation_time":""},
{"violation_date":"sdfdsf","violation_time":"sdfsdf"},
{"violation_date":"1233","violation_time":""},
{"violation_date":"test","violation_time":"time"}]'
JSON.parse(jsn) # => [{"violation_date"=>"sdfsdf", "violation_time"=>""}, {"violation_date"=>"sdfdsf", "violation_time"=>"sdfsdf"}, {"violation_date"=>"1233", "violation_time"=>""}, {"violation_date"=>"test", "violation_time"=>"time"}]
To verify json string you could use: http://www.jslint.com/.
And basic json structure: http://json.org/
UPDATED
In your case just try this:
JSON.parse('[' + params_gotton + ']')
well, received string does not contain a proper Json structure..
First convert that received param in a proper json structure and then parse it using "JSON.parse(params_gotton)".
In above received data all key and value shud be in a key value pair string format.. remove "\" symbol from received data..
it will definitely work fine..

Trying to extract key value from parsed JSON in ruby

I’m trying to parse some JSON from the twitter API and extract the value of a key (“media_url”), which is a sub-key of the key (“entities”)
so far I have:
url = 'https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&screen_name=print_broadcast&count=1'
response = RestClient.get(url)
data=response.body
result = JSON.parse(data)
How would I extract a key value from the parsed JSON?
I’ve tried
result[“entities”]
etc, but I get en error when trying to convert a string to integer... the result of my parsed JSON is an array - shouldn't this be a hash?
Sorry for the dumb questions.
Any help would be appreciated.
The JSON output is actually a list. Granted, it only has one element, but it's still a list.
First get result[0], then you can access ['entries'].

Post nested params (hash) using HTTPClient

I needed a to have a multipart http post from one app to another that included a file attachment and a nested params hash. I tried using HTTPClient which worked for the file attachment, however I could not get params to send in a nested format.
data_params = Hash.new
data_params[:params] = Hash.new
data_params[:params][:f] = Hash.new
data_params[:params][:d] = Hash.new
data_params[:params][:d][:name] = "Mich"
data_params[:params][:d][:city] = "Ostin"
data_params[:params][:f][:event] = "Sundance"
http_client = HTTPClient.new
body = data_params[:params]
response = http_client.post('http://localhost:3030/receiver/receive_test_data/', body)
with the receiver app seeing the params as {"d"=>"nameMichcityOstin","f"=>"eventSundance"} (with the hash collapsed into strings on the nested level)
I wonder if this is a limitation on http posts or am I simply doing something wrong. I have worked with JSON before, which I know supports a nested structure, but there I have no idea how to add file attachments. I appreciate any suggestions or alternative methods that would comply with 'best practices' on doing something like this.
If using Rails:
> {:a=>53,:b=>{:c=>7}}.to_query
=> "a=53&b[c]=7"
http://apidock.com/rails/ActiveSupport/CoreExtensions/Hash/to_query
I'm not sure which HTTPClient library you're using so I haven't been able to try this, but what if you use keys like this
data_params[:params]['d[name]'] = "Mich"
data_params[:params]['d[city]'] = "Ostin"
i.e. data_params[:params] is just a one level hash.
and then the receiving application will unpack this into the nested hash that you expect.

Resources