RoR: to_json on an array of hashes - ruby-on-rails

I have an array of hashes in a Rails action which i return to client in json format:
{"msg": "Got report data.Check 'report' json object. ", "success": true, "reports": "[{\"total_transfers\": 0, \"total_keywords\": 0, \"keyword\": \"plum\", \"total_duration\":1464.0, \"total_calls\": 22, \"total_sms\": 0, \"avg_duration\": 67,\"total_email\": 0}]"}
In action i do: return reports.to_json but as you can see it does not look like valid json (why the escape characters?)
In client side js code, i do reports.length and get 163??? when it should say 1 because there is only one "report" in the reports array.

As you can see "reports" is one big string, instead of an array of a hash which you'd expect (163 is the length of the string, and this is why you can see escape characters). Which json library are you using with rails? What kind of object is your array of hash exactly? It might not have the to_json method implemented...
Alternatively you might try to convert your repsonse to yaml first, from that getting json is easier.

reports_array_object = eval("(" + reports + ")");
sweet!!!!

Related

Read JSON formatted response from Google finance api

The code for get data from google-finance url:
uri =URI.parse('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK')
rs = Net::HTTP.get(uri)
rs.delete! '//'
a = JSON.parse(rs)
p a
This is the response:
[{"id"=>"15355585", "t"=>"ANDHRABANK", "e"=>"NSE", "l"=>"49.30", "l_fix"=>"49.30", "l_cur"=>"₹49.30", "s"=>"0", "ltt"=>"3:30PM GMT+5:30", "lt"=>"Jan 13, 3:30PM GMT+5:30", "lt_dts"=>"2017-01-13T15:30:00Z", "c"=>"-0.15", "c_fix"=>"-0.15", "cp"=>"-0.30", "cp_fix"=>"-0.30", "ccol"=>"chr", "pcls_fix"=>"49.45"}]
Unable to access the JSON array. Want to access the array in a['t'] manner.
Since you're dealing with a hash in an array, you have to specify the array element position as well:
require 'json'
require 'net/http'
uri = URI.parse('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK')
rs = Net::HTTP.get(uri)
rs.delete! '//'
a = JSON.parse(rs)
p a.class #=> Array
p a[0]["t"] #=> "ANDHRABANK"
Either you run loop on array then you can access using a[i]["t"] or use a[0]["t"].
Note: i is the index of array elements.
You aren't making it easy for yourself. Consider this:
require 'json'
require 'open-uri'
rs = open('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK').read
foo = JSON[rs[4..-1]].first
foo['t'] # => "ANDHRABANK"
Rather than deal with the intricacies of Net::HTTP, which is more useful as a tool to build new HTTP services, I'd recommend relying on OpenURI, or one of the many HTTP clients available. The advantage over Net::HTTP is redirection is automatically handled plus simplicity. OpenURI does have some downsides, but for a basic URL getter it's fine.
The JSON class has [] which is smart enough to convert a string into the corresponding Ruby object. It'll also serialize a Ruby object back into a String:
puts JSON[{'a' => 1}]
# >> {"a":1}
The service you're calling is returning JSON, only, in this case, it's a single-element array containing a hash. Using first makes it easy to retrieve the hash and access it normally. It's cleaner to do that than to sprinkle your code with this form:
foo[0]['t']
which is longer to type and results in a visual noise.

Swapping Rails 4 ParamsParser removes params body

I'm trying to follow this solution to add a params parser to my rails app, but all that happens is that I now get the headers but no parameters from the body of the JSON request at all. In other words, calling params from within the controller returns this:
{"controller"=>"residences", "action"=>"create",
"user_email"=>"wjdhamilton#wibble.com",
"user_token"=>"ayAJ8kDUKjCiy1r1Mxzp"}
but I expect this as well:
{"data"=>{"type"=>"residences",
"attributes"=>{"name-number"=>"The Byre",
"street"=>"Next Door",
"town"=>"Just Dulnain Bridge",
"postcode"=>"PH1 3SY",
"country-code"=>""},
"relationships"=>{"residence-histories"=>{"data"=>nil},
"occupants"=>{"data"=>nil}}}}
Here is my initializer, which as you can see is almost identical to the one in the other post:
Rails.application.config.middleware.swap(
::ActionDispatch::ParamsParser, ::ActionDispatch::ParamsParser,
::Mime::Type.lookup("application/vnd.api+json") => Proc.new { |raw_post|
# Borrowed from action_dispatch/middleware/params_parser.rb except for
# data.deep_transform_keys!(&:underscore) :
data = ::ActiveSupport::JSON.decode(raw_post)
data = {:_json => data} unless data.is_a?(::Hash)
data = ::ActionDispatch::Request::Utils.deep_munge(data)
# Transform dash-case param keys to snake_case:
data = data.deep_transform_keys(&:underscore)
data.with_indifferent_access
}
)
Can anyone tell me where I'm going wrong? I'm running Rails 4.2.7.1
Update 1: I decided to try and use the Rails 5 solution instead, the upgrade was overdue anyway, and now things have changed slightly. Given the following request:
"user_email=mogwai%40balnaan.com
&user_token=_1o3Kpzo4gTdPC2bivy
&format=json
&data[type]=messages&data[attributes][sent-on]=2014-01-15
&data[attributes][details]=Beautiful+Shetland+Pony
&data[attributes][message-type]=card
&data[relationships][occasion][data][type]=occasions
&data[relationships][occasion][data][id]=5743
&data[relationships][person][data][type]=people
&data[relationships][person][data][id]=66475"
the ParamsParser middleware only receives the following hash:
"{user":{"email":"mogwai#balnaan.com","password":"0h!Mr5M0g5"}}
Whereas I would expect it to receive the following:
{"user_email"=>"mogwai#balnaan.com", "user_token"=>"_1o3Kpzo4gTdPC2b-ivy", "format"=>"5743", "data"=>{"type"=>"messages", "attributes"=>{"sent-on"=>"2014-01-15", "details"=>"Beautiful Shetland Pony", "message-type"=>"card"}, "relationships"=>{"occasion"=>{"data"=> "type"=>"occasions", "id"=>"5743"}}, "person"=>{"data"=>{"type"=>"people", "id"=>"66475"}}}}, "controller"=>"messages", "action"=>"create"}
The problem was caused by the tests that I had written. I had not added the Content-Type to the requests in the tests, and had not explicitly converted the payload to JSON like so (in Rails 5):
post thing_path, params: my_data.to_json, headers: { "Content-Type" => "application/vnd.api+json }
The effects of this were twofold: Firstly, since params parsers are mapped to specific media types then withholding the media type meant that rails assumed its default media type (in this case application/json) so the parser was not used to process the body of the request. What confused me was that it still passed the headers to the parser. Once I fixed that problem, I was then faced with the body in the format of the request above. That is where the explicit conversion to JSON is required. I could have avoided all of this if I had just written accurate tests!

HTTParty is escaping JSON

I'm using HTTParty to send data to a remote API, however the API is complaining because the JSON being sent by HTTParty appears to be being escaped, and is thus deemed invalid.
Here's what I'm doing:
query = {"count"=>1,
"workspaces"=>
{123445=>
{"title"=>"Test Project",
"description"=>"",
"start_date"=>"2015-06-01T00:00:00.000Z",
"due_date"=>"2015-08-31T00:00:00.000Z",
"price_in_cents"=>8000,
"currency"=>"USD",
"status_key"=>130,
"custom_field_values_attributes"=>[],
"workspace_groups_attributes"=>
[{"created_at"=>"2015-07-13T11:06:36-07:00",
"updated_at"=>"2015-07-13T11:06:36-07:00",
"name"=>"Test Customer",
"company"=>true,
"contact_name"=>nil,
"email"=>nil,
"phone_number"=>nil,
"address"=>nil,
"website"=>nil,
"notes"=>nil,
"id"=>"530947",
"custom_field_values_attributes"=>[]}],
"id"=>123445}},
"results"=>[{"key"=>"workspaces", "id"=>123445}]}
Calling to_json on query escapes the JSON too:
"{\"count\":1,\"workspaces\":{\"123445\":{\"title\":\"Test Project\",\"description\":\"\",\"start_date\":\"2015-06-01T00:00:00.000Z\",\"due_date\":\"2015-08-31T00:00:00.000Z\",\"price_in_cents\":8000,\"currency\":\"USD\",\"status_key\":130,\"custom_field_values_attributes\":[],\"workspace_groups_attributes\":[{\"created_at\":\"2015-07-13T11:06:36-07:00\",\"updated_at\":\"2015-07-13T11:06:36-07:00\",\"name\":\"Test Customer\",\"company\":true,\"contact_name\":null,\"email\":null,\"phone_number\":null,\"address\":null,\"website\":null,\"notes\":null,\"id\":\"530947\",\"custom_field_values_attributes\":[]}],\"id\":123445}},\"results\":[{\"key\":\"workspaces\",\"id\":123445}]}"
Is this expected behavior to escape the JSON? Or I'm wondering if the hash I'm building for query is invalid for JSON purposes?
Any help would be greatly appreciated.
Calling to_json on query doesn't yield escaped JSON.
Try puts query.to_json to see that.
You see backslashes because #inspect method on String (and this method is called to display contents of variables to console) displays String enclosed in double quotes, and it has to escape quotes which are in the given string itself.
Your problem is probably not having proper Content-Type headers. You should do something like this:
result = HTTParty.post(url, body: query.to_json, headers: {'Content-Type' => 'application/json'})

how deserialize a json in rails

I send a http request and get a json for response like below:
{"total":"1200.0","used":"35.0","available":1165.0}
now I want deserialize this json and show to user in a table like below:
total : 1200
used : 35
availabele : 1165
I use JSON.parse(response),but I get below error:
no implicit conversion of Net::HTTPOK into String
How can I do this?
Net::HTTP has responses in body. so, Try
JSON.parse response.body
You have to pass the response.body as the parameters into the JSON.parse method then assign the method to a variable to use elsewhere in your code.
parse_res = JSON.parse(res.body)

Ruby SQS Parsing Message?

Initially I sent the converted object using .to_json which gives me a string I sent this to sqs. Now i'm retrieving the message and now it's in string form? How do I parse it back into my inital object?
--Edit
Ruby on Rails. I'm using a library to contact sqs and send the object over. Before I send it, I convert it using .to_json. Then Now, I'm writing a backend.rb file that uses that library and receives the msg and if there is a msg i want it to convert that msg back into a #project then I plan to send this #project over to a template .erb file.
To turn a JSON string into Ruby objects, call JSON.parse like so:
require 'json'
JSON.parse( '{"foo":"bar"}' )
#=> {"foo"=>"bar"}
a = JSON.parse( '[1,2,3] )
#=> [1, 2, 3]
JSON.parse( '{"name":"Gavin","cats":["Phleep","Tessa"]}' )
#=> {"name"=>"Gavin", "cats"=>["Phleep", "Tessa"]}

Resources