【问题标题】:How to parse JSON arrays with retrofit如何通过改造解析 JSON 数组
【发布时间】:2015-09-15 17:27:25
【问题描述】:

所以我有一个改造界面:

public interface RestUserInformation {
    @GET("/api/me")
    void getInfo(Callback<UserInformation> callback);
}

一个 RestAdapter:

RestAdapter userInformation = newRestAdapter.Builder()
                              .setEndpoint(IP_ADDRESS)
                              .setRequestInterceptor(requestInterceptor)
                              .build();

进行 API 调用并接收 JSON 正文答案,例如:

{"user":{ 
     "id":50,
     "email":"mail@mail.com",
     "first_name":"chris",
     "last_name":"cr",
     "birthdate":"1817-03-04",
     "gender":1,
     "country":"fr"
     {     
     "id":8,
     "language":"Spanish",
     "flag_path":"public/images/flags/Argentina.ico",
     "created_at":"2014-11-05T20:42:39.294Z",
     "updated_at":"2014-11-05T20:42:39.294Z",
     "name":"Argentina","available":false,
     "i18n_key":null
     }
    }
}

我想解析它并用它填充一个类,所以我创建了类 UserInformation.java:

public class UserInformation {
    int id;
    String email;
    String first_name;
    String last_name;
    String birthdate;
    int gender;
    String country;  }

我一直在尝试使用回调函数来做到这一点:

        RestUserInformation getUserInfo = userInformation.create(RestUserInformation.class);
        getUserInfo.getInfo(new Callback<UserInformation>() {
               @Override
               public void success(UserInformation user, Response response) {
                                            }

               @Override
               public void failure(RetrofitError error) {
                                            }
                                        });

我已经尝试了很多东西,但它不起作用,并且 UserInformation 类的属性保持为空.. 关于如何做的任何想法?

【问题讨论】:

  • 什么 POJO 映射到 JSON 的根目录?

标签: java android json retrofit


【解决方案1】:

Retrofit 默认使用 GSON 解析 JSON。

GSON 尝试使用 1:1 映射将 JSON 字段映射到 Java 对象,即 Java 类的结构必须与 JSON 的结构匹配才能执行自动解析。

这里的问题是您的 JSON 不是单个对象 - 它是另一个对象中的一个对象(标记为“用户”)。

要解决这个问题,您可以创建另一个类来封装外部对象,也可以为 GSON 创建一个自定义反序列化器。

外部对象的包装类示例:

public class UserResponse {
    public UserInformation user;
}

这是一个自定义反序列化器的例子,如果你想走这条路:

public class UserInformationAdapter implements JsonDeserializer<UserInformation> {
    @Override
    public UserInformation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // Get the root JSON object
        JsonObject rootObject = json.getAsJsonObject();

        // Get the user JSON element
        JsonElement userElement = rootObject.get("user");

        // Let GSON try to automatically deserialize the user element.
        return context.deserialize(userElement, UserInformation.class);
    }
}

你可以像这样在 Retrofit 中注册这个类型的适配器:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(UserInformation.class, new UserInformationAdapter());
Gson gson = gsonBuilder.create();
RestAdapter adapter = new RestAdapter.Builder()
    .setConverter(new GsonConverter(gson))
    .build();

这样,GSON 将使用您的UserInformationAdapter 反序列化 JSON,而不是尝试使用其默认解析策略。

【讨论】:

    【解决方案2】:

    您必须使用传递相应 json 属性的 @SerializedName 来注释字段,以便 Retrofit 可以将 JSON 解析为您的对象 试试这个:

    public class UserInformation implements Serializable {
            @SerializedName("id")
            int id;
            @SerializedName("email")
            String email;
            @SerializedName("first_name")
            String first_name;
            @SerializedName("last_name")
            String last_name;
            @SerializedName("birthdate")
            String birthdate;
            @SerializedName("gender")
            int gender;
            @SerializedName("country")
            String country;  
    }
    

    【讨论】:

    • 如果没有提供@SerializedName,Retrofit 使用什么名称?
    • Retrofit 2.0 之前,Retrofit 默认使用 GSON 对吧?所以应该提供@SerializedName
    • 如果不是,GSON 会忽略该字段吗?会发生什么?
    • 我相信没有这个注解,gson就无法正确解析json
    • 定义正确。它是否使用其他命名策略?它会抛出异常吗?它会放随机值吗?
    猜你喜欢
    • 2021-01-22
    • 2021-04-19
    • 2016-11-28
    • 2016-04-27
    • 1970-01-01
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多