改进POST方法返回错误400

时间:2018-04-16 23:17:05

标签: android retrofit

我想在Retrofit中调用POST方法(Django REST框架),为此,我从邮递员那里打电话给我,对我来说很好。

postman 我按照以下方式完成了Android部分:

API接口:

public interface SOService {

   @FormUrlEncoded
@POST("/api-auth/")
Call<Tokken> get_tokken(@Field("username") String username, @Field("password") String password);

}

APIUtility类为

public class ApiUtils {

    public static final String BASE_URL = "http://10.0.2.2:8000/";

    public static SOService getSOService() {
        return RetrofitClient.getClient(BASE_URL).create(SOService.class);
    }
}

RetrofitClient as:

public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient(String baseUrl) {

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();



        if (retrofit==null) {


            retrofit = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(clientBuilder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
        }
        return retrofit;
    }
}

最后,按以下方式调用该函数

private void signIn() {
    boolean isValid = validate();
    if (isValid) {

        mService.get_tokken(user.getText().toString(), password.getText().toString()).enqueue(new Callback<Tokken>() {
            @Override
            public void onResponse(Call<Tokken> call, Response<Tokken> response) {
                if (response.isSuccessful()) {

                    System.out.println("Te lo imprimo");
                    System.out.println(response.body().toString());
                    Toast.makeText(LoginActivity.this, "tokken recibido", Toast.LENGTH_SHORT).show();
                } else {
                    int statusCode = response.code();
                    // handle request errors depending on status code
                }
            }

            @Override
            public void onFailure(Call<Tokken> call, Throwable t) {
                Toast.makeText(LoginActivity.this, "Error al recibir tokken", Toast.LENGTH_SHORT).show();

                t.printStackTrace();
                Log.d("MainActivity", "error loading from API");

            }
        });
        /*startActivity(new Intent(this, RolSelection.class));*/
    }
}

最终结果总是一样,我在服务器上收到此消息:

  

[17 / Apr / 2018 01:12:33]“POST / api-auth / HTTP / 1.1”200 52

但在Android中我得到了这个:

  

I / System.out:Te lo imprimo                 Tokken {tokken = '空'}

知道为什么tokken为null?当我使用邮递员时,我得到一个结果。

使用Tokken类进行更新:

public class Tokken {

    @SerializedName("tokken")
    @Expose
    private String tokken;

    public String getTokken() {
        return tokken;
    }

    public void setTokken(String tokken) {
        this.tokken = tokken;
    }

    @Override
    public String toString() {
        return "Tokken{" +
                "tokken='" + tokken + '\'' +
                '}';
    }
}

3 个答案:

答案 0 :(得分:1)

更新:将Tokken类中的字段名称从@SerializedName("tokken")更改为@SerializedName("token"),如Postman附带的屏幕截图所示,以获得"token"密钥,但不是"tokken"

也许它不是根本原因,但肯定是问题之一: 你没有正确配置改装客户端,你错过了添加http客户端:

retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(clientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

答案 1 :(得分:1)

我认为你的问题是你的bean对象(Token)有一个GSON注释要序列化为tokken

如果您将@SerializedName("tokken”)更改为@SerializedName("token”),并假设请求没有其他问题,则应正确反序列化。

我不知道为什么你在一边叫它tokken而在另一边叫token,但如果可能的话我会尽量避免它,除非你打算加入单元测试以确保未来你不会忘记这一点。

另一种传递Body的方法(可能更容易,取决于......)是使用HashMap:

@POST("/api-auth/“) 
Call<Tokken> get_tokken(@Body HashMap<String, Object> body);

然后你可以传递一个包含以下内容的地图:

[“username”, “YourUsername”],
[“password”, “YourPassword”]

但是没有额外的日志记录(或者介于两者之间的代理以查看实际发生的情况),调试非常困难。

请记住,您的问题的标题是“Retrofit POST方法返回错误400”。但是您的令牌为空是您的API返回400错误的副作用.400错误是“BAD REQUEST”,所以某些东西不是您的服务器期待。

nitpick :我将您的API方法重命名为getToken(…)fetchToken(…),使其更加适合Java / Kotlin / Android,并且更加不言自明。

答案 2 :(得分:1)

两次更改

  1. tokken更改为token

    @SerializedName("tokken") @Expose private String tokken;

  2. @SerializedName("token") @Expose private String tokken;

    1. 删除SOService中的额外“\”,它应该是

      @FormUrlEncoded @POST("api-auth/")