Rails4 JSON Parameters Parse error while Create - ruby-on-rails

I am building API for Android using RoR, I am getting the Parameters for creating an object from Android is like below,
{"company"=>"{\"description\":\"Description of the company\",\"name\":\"Google\"}", "location"=>"Bangalore", "display_photo"=>#<ActionDispatch::Http::UploadedFile:0xb12dfa8 #tempfile=#<Tempfile:/tmp/RackMultipart20141119-6448-ewg4bk>, #original_filename="Male-Face-A1-icon.png", #content_type="image/*", #headers="Content-Disposition: form-data; name=\"display_photo\"; filename=\"Male-Face-A1-icon.png\"\r\nContent-Type: image/*\r\nContent-Length: 15460\r\nContent-Transfer-Encoding: binary\r\n">}
But this line giving error when parsing
"company"=>"{\"description\":\"Description of the company\",\"name\":\"Google\"}"
Because, It should be like this for Rails,
"company"=>{"description":"Description of the company","name":"Google"}
How to achieve this in Rails...
Refer this link where Android is requesting to Rails Server,
Android Code

In you params:
"company"=>
is a hash key
"{\"description\":\"Description of the company\",\"name\":\"Google\"}"
is a string, hash value
[2] pry(main)> JSON.parse "{\"description\":\"Description of the company\",\"name\":\"Google\"}"
=> {"description"=>"Description of the company", "name"=>"Google"}
gives correct output

Related

How can I parse ruby json request

I'm using api request/response on my rails app. To update avatar i've got this request(i took it from development.log file)
Started PUT "/user/avatars.json" for 127.0.0.1 at 2017-07-18 11:47:57 +0300
Processing by AvatarsController#update as JSON
Parameters: {"avatar"=>#<ActionDispatch::Http::UploadedFile:0x007fe6cbedae18 #tempfile=#<Tempfile:/var/folders/n3/5_nb_zks2k91r5ngcmb4fm9r0000gn/T/RackMultipart20170718-26576-1vss7hh.png>, #original_filename="Снимок экрана 2017-07-16 в 21.55.05.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"avatar\"; filename=\"\xD0\xA1\xD0\xBD\xD0\xB8\xD0\xBC\xD0\xBE\xD0\xBA \xD1\x8D\xD0\xBA\xD1\x80\xD0\xB0\xD0\xBD\xD0\xB0 2017-07-16 \xD0\xB2 21.55.05.png\"\r\nContent-Type: image/png\r\n">}
Now, I need to send this request from POSTMAN application. But it uses ruby syntax like =>. How can I convert it to json to use in POSTMAN?
http://3dml.free.fr/rubyhashconverter/
I don't know if you need to do it within your code or not, but the above is an online converter, takes ruby hash syntax (old and new) and gives valid JSON.
JSON doesn't support binary data(images). So in order to pass the image, you need to convert image to base64 string and use it in JSON.

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'})

Rails not getting params from HTTP request

I'm trying to POST the following data to a Rails server (running on WebRick) from Android.
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<data>
<email>email.test#name.com</email>
<password>APassw0rd</password>
<remember_me>1</remember_me>
</data>
Now, the funny thing is that these data never show up in the params field in the controller.
Webrick does not output any parsing error. (And I guess it would post an error if it received a POST with no data attached:
Started POST "/users/sign_in.xml" for 192.168.1.94 at 2012-12-14 17:33:20 +0100
Processing by Users::SessionController#create as XML
Completed 500 Internal Server Error in 22643ms
I also found no trace of the data in the request.env variable. Actually, I see no HTTP_BODY in the dump fields. How can one see the raw body of the request? Would webrick really not complain if it received a POST with no attached data?
request.env would show the data as an IO object so you wouldn't be able to see your xml directly.
request.raw_post should return the raw data.
For rails to try and parse your xml into the params hash directly you need to set the content type of the request to application/xml. The 'processing as xml' stuff means that rails will try to render an xml response and doesn't necessarily have any bearing on the format of the posted data

Trouble handling HTTP responses and parsing JSON data

I am using Ruby on Rails 3 and I would like to solve an issue with the following code where a web client application receive back some JSON data from a web service application that uses a Rack middleware in order to respond.
In the web client app model I have
response_parsed = JSON.parse(response.body)
if response_parsed["account"]
...
else
return response
end
In the above code the response.body come back from the web service app that uses a Rack middleware to respond to the web client:
accounts = Account.where(:id => ids)
[200, {'Content-Type' => 'application/json'}, accounts.to_json] # That is, response.body = accounts.to_json
Data transmission is ok, but I get the following error
TypeError
can't convert String into Integer
*Application Trace*
lib/accounts.rb:107:in `[]'
The line 107 corresponds to
if response_parsed["account"]
...
Where and what is the problem? How to solve that?
If I try to debug the respons.body I get
# Note: this is an array!
"[{\"account\":{\"firstname\":\"Semio\",\"lastname\":\"Iaven\"\"}}]"
If I'm saying something you already realize, forgive me.
It looks like your response is a one-element array with a hash in it as the first element. Because the response is an array, when you use the [] it is expecting a integer representing the index of the item in the array you'd like to access, and that is what the error message means--it expected that you'd tell it the integer value of the item you wanted, but instead you gave it a string.
If you instead do:
response_parsed[0]['account']
It seems like you'd get what you want.

Resources