【问题标题】:Retrofit not parsing JSONObject改造不解析 JSONObject
【发布时间】:2015-07-16 23:47:42
【问题描述】:

成功登录会从服务器返回以下JSONObject

{"success":true,"message":"Sign in success.","response_data":{"user_id":"24", "email_id":"user@gmail.com", "secret_code": "You did it!"}}

我想将response_data 信息放入我的User 对象中。我曾经做过这样的事情:

String getResponse = jsonObject.getString("response_data");

Gson gson = new GsonBuilder()
        .disableHtmlEscaping()
        .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
        .setPrettyPrinting()
        .serializeNulls()
        .create();

//All the data in the `response_data` is initialized in `User`
User user = gson.fromJson(getResponse, User.class);

现在我尝试在改造中做同样的事情:

初始化 RestAdapter + 接口:

public class ApiClient {
    private static RetrofitService sRetrofitService;

    public static RetrofitService getRetrofitApiClient() {
        if (sRetrofitService == null) {
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setEndpoint("http://xxx.xxx.xxx.xxx/")
                    .build();

            sRetrofitService = restAdapter.create(RetrofitService.class);
        }

        return sRetrofitService;
    }

    public interface RetrofitService {

        @FormUrlEncoded
        @POST("/login")
        public void login(@Field("email_id") String emailId, @Field ("password") String password, 
                          Callback <User> callback);                                                                    
    }
}

主活动:

  ApiClient.getRetrofitApiClient().login(email.getText().toString(), password.getText().toString(),       
      new Callback<User>() {
            @Override
            public void success(User user, Response response) {
                User user1 = user; //null
                Toast.makeText(this, "user is: "+user1.toString(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void failure(RetrofitError error) {
                Toast.makeText(this, "Failed Login", Toast.LENGTH_SHORT).show();
            }
        });

用户:

public class User {

    private String userId;
    private String emailId;
    private String code;

    public User() {

    }

    ... getters
    ... setters
}

MainActivity 中的Retrofit 代码有效,我在log 中收到此响应:

{"success":true,"message":"Sign in success.","response_data":{"user_id":"24", "email_id":"user@gmail.com", "secret_code": "You did it!"}}

但是它不会将response_data 解析为我的User 对象。

我该如何解决这个问题?

【问题讨论】:

  • 不,不幸的是,只是一个错字...我会解决的。感谢您指出这一点

标签: android parsing retrofit jsonobject


【解决方案1】:

你需要创建一个响应对象

public class UserResponse {
  private User responseData;
  private String message;
  private boolean success;
}

并更改您的回调以返回用户响应

public interface RetrofitService {
    @FormUrlEncoded
    @POST("/login")
    public void login(@Field("email_id") String emailId, @Field ("password") String password, 
                      Callback <UserResponse> callback);                                                                    
}

注意:您还需要创建自定义 Gson 实例并将其应用到其余适配器。

RestAdapter restAdapter = RestAdapter.Builder()
  .setEndpoint("xxx")
  .setConverter(new GsonConverter(gson))
  .build()

【讨论】:

  • 在 Retrofit 之前我只使用 Gson。 Gson 不是自动集成到 Retrofit 中了吗?为什么我需要声明一个自定义 Gson 实例?
  • @user2456977 您添加了一个转换器,以便您可以配置字段命名策略等选项。如果您使用所有默认值,则不必这样做。
【解决方案2】:

首先,

setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);

你想要

setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);

因为这就是您的字段的命名方式。 (例如response_data

那么,您的User 课程不代表您的服务的答案。创建一个模仿 json 对象结构的模型类。 (根据 cyroxis 的建议)。

最后,你的java成员的命名与你的json字段的命名不一致(例如secret_code vs code in User)。要么解决这个问题,要么使用 @SerializedName 将 json 字段显式匹配到 java 字段。

【讨论】:

  • 在 Retrofit 之前我只使用 Gson。 Gson 不是自动集成到 Retrofit 中了吗?为什么我需要声明一个自定义 Gson 实例?并感谢您指出不一致之处。我会修复它们
  • 如果您的 json 字段与您的 java 字段不匹配,您需要自定义您的 gson 实例。通常当json使用snake case而java使用camel case时。
  • 另外,改造不会为您做任何解释。你告诉它把数据放到一个 User 实例中,它试图这样做。而且您的数据不代表用户。它表示一个包含字段response_data 的对象,该字段是用户的数据。
【解决方案3】:

如果你做两件事可能会解决你的问题:

  1. 将 GSON Builder 上的 FieldNamingPolicy 更改为使用 LOWER_CASE_WITH_UNDERSCORES
  2. 将 UserResponse 和 User 中的变量范围更改为 public(这可能不是必需的)

【讨论】:

  • 在 Retrofit 之前我只使用 Gson。 Gson 不是自动集成到 Retrofit 中了吗?为什么我需要声明一个自定义 Gson 实例?
猜你喜欢
  • 1970-01-01
  • 2013-11-13
  • 2020-04-11
  • 2016-12-19
  • 2020-10-31
  • 1970-01-01
  • 2016-08-25
  • 2014-11-22
  • 1970-01-01
相关资源
最近更新 更多