Cool Do
Cool Do

Reputation: 277

How to make a POST request using retrofit 2?

I was only able to run the hello world example (GithubService) from the docs.

The problem is when I run my code, I get the following Error, inside of onFailure()

Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $

My API takes POST params value, so no need to encode them as JSON, but it does return the response in JSON.

For the response I got ApiResponse class that I generated using tools.

My interface:

public interface ApiService {
    @POST("/")
    Call<ApiResponse> request(@Body HashMap<String, String> parameters);
}

Here is how I use the service:

HashMap<String, String> parameters = new HashMap<>();
parameters.put("api_key", "xxxxxxxxx");
parameters.put("app_id", "xxxxxxxxxxx");

Call<ApiResponse> call = client.request(parameters);
call.enqueue(new Callback<ApiResponse>() {
    @Override
    public void onResponse(Response<ApiResponse> response) {
        Log.d(LOG_TAG, "message = " + response.message());
        if(response.isSuccess()){
            Log.d(LOG_TAG, "-----isSuccess----");
        }else{
            Log.d(LOG_TAG, "-----isFalse-----");
        }

    }
    @Override
    public void onFailure(Throwable t) {
        Log.d(LOG_TAG, "----onFailure------");
        Log.e(LOG_TAG, t.getMessage());
        Log.d(LOG_TAG, "----onFailure------");
    }
});

Upvotes: 15

Views: 33231

Answers (3)

Codemaker2015
Codemaker2015

Reputation: 15659

Let’s say we have a following JSON string and we want to use Retrofit 2 to post the string to the remote API:

{ "name": "Introduction to Unity3D", "author": "Vishnu Sivan" }

To post a JSON string with Retrofit 2, we can define a POJO that can represent the JSON that we need. For instance, a POJO represents the JSON can be defined in the following way:

public class Book {
 
  private Long id;
  private String name;
  private String author;
 
  // constructor
  // getter and setter
}

Then we can define the endpoint as below:

public interface GetDataService {

    @POST("post")
    Call<Book> addBook(@Body Book book);
}

Because we annotate the parameter with the @Body annotation, Retrofit 2 will use the converter library to serialize the parameter into JSON.

Next, let post the JSON string like we post an object with Retrofit 2:

public void testPostJson() throws IOException {

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://httpbin.org/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    GetDataService service = retrofit.create(GetDataService.class);
    Book book = new Book(1, "Introduction to Unity3D", "Vishnu Sivan");

    call.enqueue(new Callback<Book>() {
        @Override
        public void onResponse(Call<Book> call, Response<Book> response) {
            Book book = response.body();
            Log.d("book", book.getName()); //getName() is the getter method that declared in the Book model class
        }

        @Override
        public void onFailure(Call<com.tcs.artoy.model.Response> call, Throwable t) {
            Log.e("error", t.toString());
        }
    });
}

NB: Here the response we are getting is the same json format data that we have sent to the server. If you want different response than the same request object then create another model file in your project and mention that as the Response type.

If you want a POST request example, just check the following Github repository:

For more:

https://howtoprogram.xyz/2017/02/17/how-to-post-with-retrofit-2/

Upvotes: 0

Philipp Hellmayr
Philipp Hellmayr

Reputation: 302

You should be aware of how you want to encode the post params. Important is also the @Header annotation in the following. It is used to define the used content type in the HTTP header.

@Headers("Content-type: application/json")
@POST("user/savetext")
    public Call<Id> changeShortText(@Body MyObjectToSend text);

You have to encode your post params somehow. To use JSON for transmission you should add .addConverterFactory(GsonConverterFactory.create(gson)) into your Retrofit declaration.

Retrofit restAdapter = new Retrofit.Builder()
                .baseUrl(RestConstants.BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(httpClient)
                .build();

Another source of your problem could be that the JSON, that's coming from the rest backend seems to be not correct. You should check the json syntax with a validator, e.g. http://jsonlint.com/.

Upvotes: 5

Vishal Raj
Vishal Raj

Reputation: 1775

If you don't want JSON encoded params use this:

@FormUrlEncoded
@POST("/")
Call<ApiResponse> request(@Field("api_key") String apiKey, @Field("app_id") String appId);

Upvotes: 18

Related Questions