I have a hash of the format
{com: 1234, users: [{nid: 3, sets: [1,2,3,4]}, {nid: 4, sets: [5,6,7,8]}]}
which I am sending to a remote server. I am using the HTTParty
gem to do this. The code looks like this
class Api
include HTTParty
attr_accessor :headers
def initialize
@headers = { 'Content-Type' => 'application/json' }
end
def post_com(hsh)
response = self.class.post('some_url', query: hsh, headers: headers, format: :plain)
end
end
When I do
api = Api.new.post_com({com: 1234, users: [{nid: 3, sets: [1,2,3,4]}, {nid: 4, sets: [5,6,7,8]}]}
at the remote server, the hash is being sent in the following format
POST "/some_url?com=1234&users[][nid]=3&users[][sets][]=1&users[][sets][]=2&users[][sets][]=3&users[][sets][]=4&users[][nid]=4&users[][sets][]=5&users[][sets][]=6&users[][sets][]=7&users[][sets][]=8
This means for every entry in set, duplicate characeters users[][sets][]
are being sent. In operation, there can be many entries in set, and the result is the server rejects the post as having too many characters.
Is there anyway I can have the hash serialized with far less duplication. For instance if I just do
{com: 1234, users: [{nid: 3, sets: [1,2,3,4]}, {nid: 4, sets: [5,6,7,8]}]}.to_json
I receive
"{\"com\":1234,\"users\":[{\"nid\":3,\"sets\":[1,2,3,4]},{\"nid\":4,\"sets\":[5,6,7,8]}]}"
which has far fewer characters.
HTTParty, by default, converts the :query
hash into what it calls 'rails style query parameters':
For a query:
get '/', query: {selected_ids: [1,2,3]}The default query string looks like this:
/?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
Since you are doing a POST, it is possible/preferable to send your hash in the body of the request rather than in the query string.
def post_com(hsh)
self.class.post('some_url', body: hsh.to_json, headers: headers, format: :plain)
end
This has the advantage that it doesn't do any transformation of the payload and the query string length limit doesn't apply anyway.
For the record, you can disable the default 'rails style' encoding like this:
class Api
include HTTParty
disable_rails_query_string_format
...
end
You can also roll your own custom query string normalizer by passing a Proc
to query_string_normalizer
.