Nested HTTP params on ruby HTTP requests

Discussion in 'Ruby' started by Dave Garcia, Jun 4, 2009.

  1. Dave Garcia

    Dave Garcia Guest

    Hi,

    I'm using ruby HTTP classes to send POST requests to a server. The
    problem is that I'm posting some many-levels hierarchical structures on
    my form . When POST parameters are simple key/value there's no
    serialization problem with form_data method on PostRequest.

    { :a => :b} => "a=b"

    When the values are arrays it works fine too

    { :a => [:b,:c,:d]} => "a[]=b&a[]=c&a[]=d"

    But when values are hashes serialization doesn't work as expected.

    For example
    { :a => [{:b => :c}, {:d => :e}]} => "a[]=c&a[][d]=e"

    I don't know if there's any other way to do it but browsing the code it
    seems that only one nesting level is supported (maybe is an issue on my
    ruby version 1.8.6).

    I developed a tiny serialization method. Is a quick and dirty code (the
    first release I've made) but it works for me.

    module FormSerializer
    require "erb"
    include ERB::Util

    def serialize_form_data(data, path = "",serialized_params = [])
    if data.kind_of? Hash
    data.each_pair{|k,v| token = (path == "" ? url_encode(k) :
    "[#{url_encode(k)}]"); serialize_form_data(v, "#{path}#{token}",
    serialized_params)}
    elsif data.kind_of? Array
    data.each{|v| serialize_form_data(v, "#{path}[]",
    serialized_params) }
    else
    #end of recursion
    serialized_params << "#{path}=#{url_encode(data)}"
    end

    return serialized_params.join("&") if (path == "")
    end


    #{ :a => :b} = "a=b"
    #{ :a => [:b,:c,:d]} = "a[]=b&a[]=c&a[]=d"
    #{ :a => :b, :b => :c} = "a=b&b=c"
    #{ :a => {:b => :c}} = "a = c"
    #{ :a => [{:b => :c}, {:d => :e}]} = "a[] = c & a[][d] = e"


    end

    After this I only needed to modify

    def form_data(params, sep = '&')
    self.body = serialize_form_data(params)
    self.content_type = 'application/x-www-form-urlencoded'
    end

    I just finished the code some hours ago, basic testing has been
    performed.
    Hope this will be useful for anyone! :)

    Best regards

    Dave Garcia
    --
    Posted via http://www.ruby-forum.com/.
    Dave Garcia, Jun 4, 2009
    #1
    1. Advertising

  2. Dave Garcia wrote:
    > { :a => :b} => "a=b"
    >
    > When the values are arrays it works fine too
    >
    > { :a => [:b,:c,:d]} => "a[]=b&a[]=c&a[]=d"
    >
    > But when values are hashes serialization doesn't work as expected.
    >
    > For example
    > { :a => [{:b => :c}, {:d => :e}]} => "a[]=c&a[][d]=e"


    Well, firstly, you didn't say what framework is parsing this form data.
    But also, in this example you're doing mixtures of arrays and hashes,
    and I don't think that's likely to work. (Of course, feel free to make a
    patch for whatever framework you're using, and submit it)

    I think you'll have more luck with hashes of hashes:

    a[c]=d&a[d]=e

    will probably be deserialised as {'a'=>{'b'=>{'c'=>'d','e'=>'f'}}}

    At least, I'm reasonably sure Rails can handle this. Rack had some
    issues with its parsing of nested form-data parameters which may or may
    not have been fixed yet. And if you're using some other framework with
    its own parameter parsing, then you'll need to look at that separately.

    > I don't know if there's any other way to do it but browsing the code it
    > seems that only one nesting level is supported (maybe is an issue on my
    > ruby version 1.8.6).


    It's unlikely to be anything to do with your ruby version, unless the
    deserialisation is being done by some code which is bundled with ruby
    (the CGI library??)
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Jun 4, 2009
    #2
    1. Advertising

  3. Of course, I meant

    a[c]=d&a[e]=f

    will probably be deserialised as {'a'=>{'b'=>{'c'=>'d','e'=>'f'}}}
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Jun 4, 2009
    #3
  4. Dave Garcia

    Dave Garcia Guest

    Hi Brian,

    On the client side:

    params = {:a=>[{:d=>:e, :b=>:c}]}
    serialize_form_data(params) # "a[][d]=e&a[]=c"

    On the server side Rails 2.3.2 works fine deserializing my params are :

    {"a"=>[{"b"=>"c", "d"=>"e"}], "action"=>"show",
    "controller"=>"identities"}

    Maybe you're right , I'll talk with the guys in RoR maybe they're
    interested.

    Best regards

    Dave

    Brian Candler wrote:
    > Of course, I meant
    >
    > a[c]=d&a[e]=f
    >
    > will probably be deserialised as {'a'=>{'b'=>{'c'=>'d','e'=>'f'}}}


    --
    Posted via http://www.ruby-forum.com/.
    Dave Garcia, Jun 4, 2009
    #4
  5. Dave Garcia wrote:
    > On the client side:
    >
    > params = {:a=>[{:d=>:e, :b=>:c}]}
    > serialize_form_data(params) # "a[][d]=e&a[]=c"
    >
    > On the server side Rails 2.3.2 works fine deserializing my params are :
    >
    > {"a"=>[{"b"=>"c", "d"=>"e"}], "action"=>"show",
    > "controller"=>"identities"}


    Then I've lost you, because that all seems to be working fine (both
    serialize_form_data and RoR deserializing it)

    So can you give an example of what the problem actually is?

    > But when values are hashes serialization doesn't work as expected.
    >
    > For example
    > { :a => [{:b => :c}, {:d => :e}]} => "a[]=c&a[][d]=e"


    Maybe I misunderstood this. Is this what your code actually produces, or
    what you expected it to produce? If not, what did you expect it to
    produce?
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Jun 4, 2009
    #5
  6. Dave Garcia

    Dave Garcia Guest

    Hi Brian,

    you're not lost I explained myself terrible, my fault ;).

    Those example of serializations are produced by my code. I tested it
    only sending post request vs rails, but it worked fine with all proposed
    examples.

    Sorry for by bad explanation.

    Best regards

    Dave

    Brian Candler wrote:
    > Dave Garcia wrote:
    >> On the client side:
    >>
    >> params = {:a=>[{:d=>:e, :b=>:c}]}
    >> serialize_form_data(params) # "a[][d]=e&a[]=c"
    >>
    >> On the server side Rails 2.3.2 works fine deserializing my params are :
    >>
    >> {"a"=>[{"b"=>"c", "d"=>"e"}], "action"=>"show",
    >> "controller"=>"identities"}

    >
    > Then I've lost you, because that all seems to be working fine (both
    > serialize_form_data and RoR deserializing it)
    >
    > So can you give an example of what the problem actually is?
    >
    >> But when values are hashes serialization doesn't work as expected.
    >>
    >> For example
    >> { :a => [{:b => :c}, {:d => :e}]} => "a[]=c&a[][d]=e"

    >
    > Maybe I misunderstood this. Is this what your code actually produces, or
    > what you expected it to produce? If not, what did you expect it to
    > produce?


    --
    Posted via http://www.ruby-forum.com/.
    Dave Garcia, Jun 5, 2009
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fernando Arámburu

    web requests and mobile requests

    Fernando Arámburu, Apr 8, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    435
    Joerg Jooss
    Apr 8, 2005
  2. Barry
    Replies:
    9
    Views:
    431
    Ara.T.Howard
    Sep 15, 2005
  3. Ben Aroia
    Replies:
    5
    Views:
    235
    Ben Aroia
    Mar 30, 2008
  4. David Sainte-claire
    Replies:
    1
    Views:
    91
    yermej
    Nov 23, 2009
  5. Eki
    Replies:
    0
    Views:
    627
Loading...

Share This Page