【问题标题】:Gson can not convert api responseGson 无法转换 api 响应
【发布时间】:2019-11-01 11:07:19
【问题描述】:

我只是想在使用 Retrofit 访问 API 后显示用户数据。我的 api 响应是:

{ 
   "password":"111222333",
   "name":"test name",
   "email":"testem@gmail.com",
   "username":"test1",
   "customer_id":"201060",
   "phone":"0196789"
}

但不幸的是,我得到了

“应为 BEGIN_OBJECT,但在第 1 行第 1 列路径 $ 处为 STRING” 错误。

我完全坚持显示我的 json 响应。

我的 User.java 类:


    public class User {
      @SerializedName("name")
      @Expose
      private String name;
      @SerializedName("email")
      @Expose
      private String email;
      @SerializedName("username")
      @Expose
      private String username;
      @SerializedName("customer_id")
      @Expose
      private String customerId;
      @SerializedName("phone")
      @Expose
      private String phone;
      @SerializedName("password")
      @Expose
      private String password;
      public String getName() {
        return name;
      }
      public String getEmail() {
        return email;
      }
      public String getUsername() {
        return username;
      }
      public String getCustomerId() {
        return customerId;
      }
      public String getPhone() {
        return phone;
      }
      public String getPassword() {
        return password;
      }
    }

我的登录类:


    Gson gson = new GsonBuilder().setLenient().create();
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("https://us-central1-gmx-notification.cloudfunctions.net/")
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
            all_api = retrofit.create(allApi.class);
    private void getUserDetails(String userName,String passWord){
            Call<User> call = all_api.getUserDetails(userName,passWord);
            call.enqueue(new Callback<User>() {
                @Override
                public void onResponse(Call<User> call, Response<User> response) {
                    if(!response.isSuccessful()){
                        Log.d(response.body());
                    }
                    else{
                        User user = response.body();
                        String content = "";
                        content+= "Name: "+user.getName()+"\n";
                        content+= "Email: "+user.getEmail()+"\n";
                        content+= "Customer ID: "+user.getCustomerId()+"\n";
                        content+= "Phone: "+user.getPhone()+"\n";
                        Log.d(content);
                  }
    });
    }

和我的改造 api 类:


    package com.material.components;
    import java.util.List;
    import retrofit2.Call;
    import retrofit2.http.GET;
    import retrofit2.http.Query;
    public interface allApi {
      @GET("login")
      Call <User> getUserDetails(
              @Query("email") String email,
              @Query("password") String password
      );
    }

【问题讨论】:

  • 能否附上 Postman 的截图,我们可以看到来自后端的模型?因为从您的错误中,我看到您的模型无法响应,但是您的模型看起来不错。我猜你的回答有点像这样 { data { 'usermode' } }
  • 请发布您在点击 api 后得到的完整响应字符串
  • 如果您没有 Postman,您可以将 Interceptor 添加到 OkHttpClient 以查看后端发送给您的内容。

标签: android gson retrofit2


【解决方案1】:

当我打你时 api https://us-central1-gmx-notification.cloudfunctions.net/login?email=qwery@gmail.com&password=12345678

我收到了这个回复

错误:无法处理请求

因此,正如您的错误所说,您期望 Object 但得到了一个字符串。所以,或者后端出错,或者请求不正确,或者你忘记在请求中添加一些东西(Header 或其他东西......)。

当然,您的模型中没有的问题只是没有您在响应中期望的模型。在 OkHttpClient 中添加拦截器,看看你能确定什么。

你需要将此依赖添加到 gradle

implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'

这是一个代码示例,您的 API 将在日志中打印所有网络内容:

public class NetworkManager {

    private static RESTAuthService restAuthService;

    /*timeout values in seconds*/
    private static final int CONNECTION_TIMEOUT = 10;
    private static final int WRITE_TIMEOUT = 10;
    private static final int READ_TIMEOUT = 10;

    static RESTAuthService getRESTAuthService() {
        if (restAuthService == null) {
            synchronized (NetworkManager.class) {
                if (restAuthService == null) {

                    OkHttpClient client = new OkHttpClient.Builder()
                            .addInterceptor(new RESTInterceptor())
                            .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
                            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                            .build();

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

                    restAuthService = retrofit.create(RESTAuthService.class);
                }
            }
        }
        return restAuthService;
    }

    private static class RESTInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            Buffer buffer = new Buffer();
            if (request.body() != null) {
                request.body().writeTo(buffer);
            }
            Log.d("HTTP Request", "Request to " + request.url().toString()
                    + "\n" + request.headers().toString()
                    + "\n" + buffer.readUtf8());
            long t1 = System.nanoTime();
            Response response = chain.proceed(request);
            long t2 = System.nanoTime();

            String msg = response.body().string();
            msg = msg.replace("\r", ""); // Note: Messages with '\r' not displayed correctly in logcat

            Log.d("HTTP Response", String.format("Response from %s in %.1fms%n\n%s",
                    response.request().url().toString(), (t2 - t1) / 1e6d, msg));

            Log.d("HTTP Response", "Response code = " + response.code());

            return response.newBuilder()
                    .body(ResponseBody.create(response.body().contentType(), msg))
                    .build();
        }
    }
    }

您的 MyLogin 类将是这样的:

public class MuLogin {
/*timeout values in seconds*/
    private static final int CONNECTION_TIMEOUT = 10;
    private static final int WRITE_TIMEOUT = 10;
    private static final int READ_TIMEOUT = 10;

    allApi = all_api;

    OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new RESTInterceptor())
        .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
        .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
        .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
        .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://us-central1-gmx-notification.cloudfunctions.net/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();

    all_api =retrofit.create(allApi.class);

    public void getUserDetails(String userName, String passWord) {
        Call<User> call = all_api.getUserDetails(userName, passWord);
        call.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                if (!response.isSuccessful()) {
                    Log.d(response.body());
                } else {
                    User user = response.body();
                    String content = "";
                    content += "Name: " + user.getName() + "\n";
                    content += "Email: " + user.getEmail() + "\n";
                    content += "Customer ID: " + user.getCustomerId() + "\n";
                    content += "Phone: " + user.getPhone() + "\n";
                    Log.d(content);
                }
            });
        }
    }
    private static class RESTInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            Buffer buffer = new Buffer();
            if (request.body() != null) {
                request.body().writeTo(buffer);
            }
            Log.d("HTTP Request", "Request to " + request.url().toString()
                    + "\n" + request.headers().toString()
                    + "\n" + buffer.readUtf8());
            long t1 = System.nanoTime();
            Response response = chain.proceed(request);
            long t2 = System.nanoTime();

            String msg = response.body().string();
            msg = msg.replace("\r", ""); // Note: Messages with '\r' not displayed correctly in logcat

            Log.d("HTTP Response", String.format("Response from %s in %.1fms%n\n%s",
                    response.request().url().toString(), (t2 - t1) / 1e6d, msg));

            Log.d("HTTP Response", "Response code = " + response.code());

            return response.newBuilder()
                    .body(ResponseBody.create(response.body().contentType(), msg))
                    .build();
        }
    }
}

【讨论】:

  • 嗨尤金·特罗扬斯基,感谢您的回复。实际上我应该在哪里写这个 RESTAuthService ...它是在我上面的 Login 类中还是在改造 api 类中?但是,请尝试点击us-central1-gmx-notification.cloudfunctions.net/…
  • @EnayetHossain 我的 RESTAuthService 它是您的 api 接口。在“我的登录类”中添加 RESTInterceptor 作为内部类,然后按照我的示例创建您的改造。
  • 谢谢...实际上我的输入文本没有正确传递给 API。现在它正在工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多