Trying to parse request body in Grape API

1.2k views Asked by At

So I have an API where one of the entry points looks something like:

module SomeModule
  module SomeOtherModule
    class Users < SomeModule::SomeOtherModule::Base
      helpers do
        params :user do
          requires :user, type: Hash do
            requires :device_id, type: String, desc: "Device ID"
          end
        end
      end

      desc "Some description"
      params do
        use :user
      end

      put "/", route_name: :v1_put_user_path do
        ...
      end
    end
  end
end

SomeModule::SomeOtherModule::Base inherits from Grape::API

My client is sending the params in the body - which look like:

{"user[device_id]":"xyz"}

Since this come like a string the I fail to recognise them.Therefore return:

{"error":"user is missing"}

This means that on my server I'm getting:

{"user[device_id]"=>"00999877",
  "route_info"=>
   ...

When I'm expecting to see:

{"user"=>{"device_id"=>"00999877"},
  "route_info"=>
  ...

Any ideas on how should I define my params?...or maybe someone has stumble upon this issue and can provide some solution

1

There are 1 answers

5
Marlon On

You have to define your params block like this:

module SomeModule
    module SomeOtherModule
        class Users < SomeModule::SomeOtherModule::Base
            params do
                group :user, type: Hash do
                    requires :device_id, type: String, desc: "Device ID"
                end
            end
            put "/", route_name: :v1_put_user_path do
                ...
            end
        end
    end
end

UPDATE

Explaining the solution...

If your client is sending a JSON like the code below, then you have to define a group block and define the type parameter as Hash. The same rule applies when your client sends a "form-field" like user[device_id].

{ user: { device_id: 1 } }

UPDATE 2

I've just noticed that your client is sending an incorrect JSON to your service. This JSON shouldn't be...

{"user[device_id]":"xyz"} 

...because it's not what your API is expecting. Instead, it should send

{ user: { device_id: "xyz" } }.