Use gson and create a model class for the location.
Add the following dependencies to your build.gradle.
compile 'com.squareup.retrofit2:converter-gson:2.0.0' compile 'com.google.code.gson:gson:2.5'
Create a model to represent the location.
public class Location { double lat; double lng; String location; public Location(double lat, double lon, String place) { this.lat = lat; this.lon = long; this.place = place; } }
If the variable names for the payload fields don't match the actual required name for the endpoint you will need to add the annotation @SerializedName([expected name])
ex:
import com.google.gson.annotations.SerializedName; public class Location { @SerializedName("lat") double latitude; @SerializedName("lng") double longitude; @SerializedName("place") String location; public Location(double lat, double lon, String place) { latitude = lat; longitude = long; location = place; } }
Define the api interface.
public interface Api { @POST("upload/") @Multipart Call<ResponseBody> uploadFile(@Part("title") RequestBody title, @Part MultipartBody.Part imageFile, @Part("location") Location location ); }
Create a Retrofit instance and call the api.
File file; // create retrofit instance Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://baseurl.com/api/") .addConverterFactory(GsonConverterFactory.create()) .build(); // create api instance Api api = retrofit.create(Api.class); // create call object Call<ResponseBody> uploadFileCall = api.uploadFile( RequestBody.create(MediaType.parse("text/plain"), "title"), MultipartBody.Part.createFormData( "file", file.getName(), RequestBody.create(MediaType.parse("image"), file)), new Location(48.8583, 2.29232, "Eiffel Tower")); // sync call try { ResponseBody responseBody = uploadFileCall.execute().body(); } catch (IOException e) { e.printStackTrace(); } // async call uploadFileCall.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { // TODO } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // TODO } });
You will need to change the MediaType.parse() call if you are not using an image file.
You can similarly create a custom response type object and replace ResponseBody with it to receive a deserialized result object.
Let me know if this works. I didn't have a chance to test in your exact scenario obviously but I'm fairly confident this should work. The only part I'm not 100% on is whether @Part("location") Location location should be @Body("location") Location location