3

All,

I'm starting to user RetroFit for the first time, and it's pretty awesome. That said, I'm running into a road block when formatting a POST request.

The API I'm using specifies that to create a user, I need to send the user object like this:

{
"user": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "john@doe.com",
    "password": "jigglypuff123",
    "password_confirmation": "jigglypuff123"
  }
}

I know that I can send a JsonObject in this form, but I'd instead like to leverage RetroFit.

If I pass in a User object, it doesn't get wrapped in user. Just

{
    "first_name": "John",
    "last_name": "Doe",
    "email": "john@doe.com",
    "password": "jigglypuff123",
    "password_confirmation": "jigglypuff123"
  }

is sent.

I tried using the @Field annotation, and ended up with this:

@POST("/users")
    void createUser(@Field("user[first_name]") String first, @Field("user[last_name]") String last, @Field("user[email]") String email, @Field("user[password]") String password, @Field("user[password_confirmation]") String password_confirmation, Callback<User> cb);

I ended up with this error:

@Field parameters can only be used with form encoding. (parameter #1)

Does anyone know how to achieve this?

coder
  • 10,460
  • 17
  • 72
  • 125

3 Answers3

5

Try this:

@FormUrlEncoded
@POST("/users")
void createUser(@Field("user") User user, Callback<User> cb);

let me know what happens :)

amilcar-sr
  • 1,050
  • 9
  • 21
2

Use this for interface

 @FormUrlEncoded
 @POST("/users/create.json")
 public void insertUser(
         @Field("user[name]") String name,
         @Field("user[email]") String email,
         @Field("user[password]") String password,
         Callback<Response> callback);

And In android activity use this

 private void insertUser(){
    //Here we will handle the http request to insert user to mysql db
    //Creating a RestAdapter
    RestAdapter adapter = new RestAdapter.Builder()
            .setEndpoint(ROOT_URL) //Setting the Root URL
            .build(); //Finally building the adapter

    //Creating object for our interface
    RegisterAPI api = adapter.create(RegisterAPI.class);

    //Defining the method insertuser of our interface
    api.insertUser(

            //Passing the values by getting it from editTexts
           mname,
            memail,
            mpass,

            //Creating an anonymous callback
            new Callback<Response>() {
                @Override
                public void success(Response result, Response response) {
                    //On success we will read the server's output using bufferedreader
                    //Creating a bufferedreader object
                    BufferedReader reader = null;

                    //An string to store output from the server
                    String output = "";

                    try {
                        //Initializing buffered reader
                        reader = new BufferedReader(new InputStreamReader(result.getBody().in()));

                        //Reading the output in the string
                        output = reader.readLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    //Displaying the output as a toast
                    Toast.makeText(register.this, output, Toast.LENGTH_LONG).show();
                }

                @Override
                public void failure(RetrofitError error) {
                    //If any error occured displaying the error as toast
                    Toast.makeText(register.this, error.toString(),Toast.LENGTH_LONG).show();
                }
            }
    );
}

Where mname and memail is string which use want to pass and In rails use this def create @user = User.new(user_params)

respond_to do |format|
  if @user.save
    format.html { redirect_to @user, notice: 'User was successfully created.' }
    #format.json { render :text, status: :created, location: @user}
    format.json { render :status => 200,
          :json => { :success => true,
                     :info => "Registered Successfully" }}
  else
    format.html { render :new }
    format.json { render json: @user.errors, status: :unprocessable_entity }
  end
end
end

def user_params
  params.require(:user).permit(:name, :email, :password)
end
Arpit bandil
  • 204
  • 2
  • 9
0

I do not know whether you have solved your issue, but for Retrofit 2 this should work:

@POST("/users/")
Call<User> createUser(
    @Query("user[first_name]") String firstName,
    @Query("user[last_name]") String lastName,
    @Query("user[email]") String email,
    @Query("user[password]") String password,
    @Query("user[password_confirmation]") String confirmation
);

So, comparing to your code - the only thing that changes is @Field annotation that should be replaced with @Query annotation (and of course Retrofit to Retrofit 2 adaptation changes).

At the very end - for the above case remember to use SSL protocol to handle data encryption.

Tomasz Dzieniak
  • 2,765
  • 3
  • 24
  • 42