10

I'm very new to ruby and trying some basic stuff. When I send HTTP request to the server using:

curl -v -H "Content-Type: application/json" -X GET -d "{"myrequest":"myTest","reqid":"44","data":{"name":"test"}}" localhost:8099

My server sees JSON data as "{myrequest:myTest,reqid:44,data:{name:test}}"

But when I send the request using the following ruby code:

require 'net/http'

@host = 'localhost'
@port = '8099'

@path = "/posts"

@body = ActiveSupport::JSON.encode({
    :bbrequest => "BBTest", 
    :reqid => "44", 
    :data => 
    {
        :name => "test"
    }
})

request = Net::HTTP::Post.new(@path, initheader = {'Content-Type' =>'application/json'})
request.body = @body
response = Net::HTTP.new(@host, @port).start {|http| http.request(request) }
puts "Response #{response.code} #{response.message}: #{response.body}"

It sees it as "{\"bbrequest\":\"BBTest\",\"reqid\":\"44\",\"data\":{\"name\":\" test\"}}" and server is unable to parse it. Perhaps there are some extra options I need to set to send request from Ruby to exclude those extra characters?

Can you please help. Thanks in advance.

Bilal Wahla
  • 665
  • 1
  • 12
  • 28
  • 1
    Not an answer to your question, but using RestClient should lessen the amount of work you need to do, and I know it makes sending JSON light work: https://github.com/archiloque/rest-client – d11wtq Jul 05 '11 at 13:23
  • `JSON.parse("{\"bbrequest\":\"BBTest\",\"reqid\":\"44\",\"data\":{\"name\":\" test\"}}")` works OK are you sure that you parsing this string ? – Bohdan Jul 05 '11 at 13:31
  • Are you *sure* the problem is that the escape characters are being sent to the server, and aren't just irb or inspect output? Because the code you show doesn't put in those characters. – Mark Thomas Jul 05 '11 at 13:54

2 Answers2

3

What you are doing on the shell produces invalid JSON. Your server should not accept it.

  $echo "{"myrequest":"myTest","reqid":"44","data":{"name":"test"}}"
      {myrequest:myTest,reqid:44,data:{name:test}}

This is JSON with unescaped keys and values, will NEVER work. http://jsonlint.com/ If your server accept this "sort of kind of JSON" but does not accept the second one in your example your server is broken.

My server sees JSON data as "{myrequest:myTest,reqid:44,data:{name:test}}"

Your server sees a string. When you will try to parse it into JSON it will produce an error or garbage.

It sees it as "{\"bbrequest\":\"BBTest\",\"reqid\":\"44\",\"data\":{\"name\":\" test\"}}"

No this is how it's printed via Ruby's Object#inspect. You are printing the return value of inspect somewhere and then trying to judge whether it's valid JSON - it is not, since this string you've pasted in is made to be pasted into the interactive ruby console (irb) or into a ruby script, and it contains builtin escapes. You need to see your JSON string raw, just print the string instead of inspecting it.

I think your server is either broken or not finished yet, your curl example is broken and your ruby script is correct and will work once the server is fixed (or finished). Simply because

  irb(main):002:0> JSON.parse("{\"bbrequest\":\"BBTest\",\"reqid\":\"44\",\"data\":{\"name\":\" test\"}}")
        # => {"bbrequest"=>"BBTest", "reqid"=>"44", "data"=>{"name"=>" test"}}
Julik
  • 7,676
  • 2
  • 34
  • 48
1

Your problem is something other than the existence of escape characters in the string. Those are not put in by the code you show, but by irb or .inspect. If you put in a simple puts @body in your code (or in a Rails context, logger.debug @body), you'll see this. Here's an irb session showing the difference:

ruby-1.9.2-p180 :002 > require 'active_support'
 => true 
ruby-1.9.2-p180 :003 > json = ActiveSupport::JSON.encode({
ruby-1.9.2-p180 :004 >           :bbrequest => "BBTest", 
ruby-1.9.2-p180 :005 >           :reqid => "44", 
ruby-1.9.2-p180 :006 >           :data => 
ruby-1.9.2-p180 :007 >           {
ruby-1.9.2-p180 :008 >                 :name => "test"
ruby-1.9.2-p180 :009?>           }
ruby-1.9.2-p180 :010?>     })
 => "{\"bbrequest\":\"BBTest\",\"reqid\":\"44\",\"data\":{\"name\":\"test\"}}" 
ruby-1.9.2-p180 :013 > puts json
{"bbrequest":"BBTest","reqid":"44","data":{"name":"test"}}
 => nil 

In any case, the best way to do json encoding in Rails is not to call ActiveSupport::JSON.encode directly, but rather override as_json in your model or use the serializable_hash feature. This will make your code cleaner as well. See the top answers to this stackoverflow question for details.

Community
  • 1
  • 1
Mark Thomas
  • 37,131
  • 11
  • 74
  • 101
  • No I'm not doing anything else other than that of the code above. I print this @body on my web page and it displays fine. But when sent over HTTP gets those extra characters that server doesn't recognise. Can you please forward me to some example that uses serializable_hash feature? – Bilal Wahla Jul 07 '11 at 09:26