1

I have an API which expects a list of exercises as input:

exercises[0][duration]=10
exercises[0][type]=jump
exercises[1][duration]=20
exercises[1][type]=roll

On Android side, I have my API class built using Retrofit.

How do I pass my List<Exercise> to the API method in order to get the above parameters.

Currently tried:

@FormUrlEncoded
@POST("api/v1/patient/{id}/workout")
fun addPatientWorkout(@Path("id") id: Long,
                      @Field("title") title: String,
                      @Field("exercises[]") exercises: List<Map<String,String>>)
        : Single<Response<Workout>>

But that does not give what I expect. Instead:

exercises[]={duration:10, type=jump}&exercises[]={duration:20, type=roll}

Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124

2 Answers2

1

What I was looking for is the @FieldMap annotation. That allows to build a map of name/values to pass as POST parameters.

@FormUrlEncoded
@POST("api/v1/patient/{id}/workout")
fun addPatientWorkout(@Path("id") id: Long,
                      @Field("title") title: String,
                      @FieldMap exercises: Map<String,String>)
        : Single<Response<Workout>>

And that gets called with the following code:

    val exerciseFields: MutableMap<String, String> = mutableMapOf()
    workout.exercises.forEachIndexed { index, exercise ->
        exerciseFields["exercises[$index][duration]"] = exercise.duration.toString()
        exerciseFields["exercises[$index][type]"] =exercise.type.name.toLowerCase()
    }

    return addPatientWorkout(
            workout.patient?.id ?: -1,
            workout.title,
            exerciseFields)
Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124
0

Format it and post as a String instead of List<Map<String,String>> because retrofit always converts maps into json.

You can convert it as follows :

        Exercise[] exercises = new Exercise[2];
        exercises[0] = new Exercise(10, "jump");
        exercises[1] = new Exercise(20, "roll");

        String postString = "";

        for(int i = 0; i < exercises.length; i++) {

            Exercise ex = exercises[i];
            postString += "exercises[" + i +"][duration]=" + ex.duration + "\n";
            postString += "exercises[" + i +"][type]=" + ex.type + "\n";
        }

        System.out.println(postString);

Exercise class :

    class Exercise {

        public Exercise(int duration, String type) {

            this.duration = duration;
            this.type = type;
        }

        int duration;
        String type;
    }

Your API function will look like this :

@FormUrlEncoded
@POST("api/v1/patient/{id}/workout")
fun addPatientWorkout(@Path("id") id: Long,
                      @Field("title") title: String,
                      @Field("exercises"): exercises, String)
        : Single<Response<Workout>> 
Vaibhav Jani
  • 12,428
  • 10
  • 61
  • 73