如何使用Retrofit 2和Gson来模拟JSON响应“密钥”频繁更改的数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Retrofit 2和Gson来模拟JSON响应“密钥”频繁更改的数据相关的知识,希望对你有一定的参考价值。

android应用程序中,我尝试使用Retrofit 2 / Gson来检索此JSON响应中的数据。 JSON响应中的“bpi”包含一组键/值对,其中键是日期。

建模我的类来存储这些数据的好方法是什么? (我想最终绘制数据。)

我知道http://www.jsonschema2pojo.org/但输出不起作用,因为JSON“键”每天都在变化。

JSON响应在过去31天内返回日期/值对:

{
  "bpi": {
    "2017-11-30": 9916.5363,
    "2017-12-01": 10859.5625,
    "2017-12-02": 10895.0138,
    "2017-12-03": 11180.8875,
    "2017-12-04": 11616.855,
    "2017-12-05": 11696.0583,
    "2017-12-06": 13708.9913,
    "2017-12-07": 16858.02,
    "2017-12-08": 16057.145,
    "2017-12-09": 14913.4038,
    "2017-12-10": 15036.9563,
    "2017-12-11": 16699.6775,
    "2017-12-12": 17178.1025,
    "2017-12-13": 16407.2025,
    "2017-12-14": 16531.0838,
    "2017-12-15": 17601.9438,
    "2017-12-16": 19343.04,
    "2017-12-17": 19086.6438,
    "2017-12-18": 18960.5225,
    "2017-12-19": 17608.35,
    "2017-12-20": 16454.7225,
    "2017-12-21": 15561.05,
    "2017-12-22": 13857.145,
    "2017-12-23": 14548.71,
    "2017-12-24": 13975.4363,
    "2017-12-25": 13917.0275,
    "2017-12-26": 15745.2575,
    "2017-12-27": 15378.285,
    "2017-12-28": 14428.76,
    "2017-12-29": 14427.87,
    "2017-12-30": 12629.8138
  }
}
答案

您不能将GSON用于此类数据。 GSON需要最终的密钥名称。

我让Retrofit将其解析为JSONObject,然后手动找到“bpi”对象,并遍历每个子节点,然后创建我自己的包含日期和值的对象。 (或者,如果您愿意,可以将它们存储在HashMap中)。

另一答案

您可以将数据读取为哈希映射声明您的bpi对象,如下所示:

@SerializedName("bpi")
public final JsonElement bpi;

并解析它:

public HashMap<String, String> getDataFromJson(final JsonElement bpi) {
    Type listType = new TypeToken<HashMap<String, String>>() {
    }.getType();
    return new Gson().fromJson(bpi, listType);
}
另一答案

使用custom deserializer根据您自己的逻辑手动解析传入的Json数据。然后,告诉Retrofit将它与addConverterFactory方法一起使用。

首先,像这样创建一个JsonDeserializer<MyType>(其中的逻辑只是一个例子):

JsonDeserializer<MyType> deserializer = new JsonDeserializer<>() {  
    @Override
    public MyType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();

        JsonObject bpiObject = jsonObject.get("bpi").getAsJsonObject();
        Map<Date, Float> data = new HashMap<>();
        for (Map.Entry<String, JsonElement> entry : bpiObject.entrySet()) {
            Date date = new SimpleDateFormat("yyyy-MM-dd").parse(entry.getKey());
            float value = entry.getValue().getAsFloat();
            data.put(date, value)
        }

        return new MyType(data);
    }
};

然后,创建您的Gson对象并注册您的反序列化器:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(MyType.class, deserializer);
        .create();

最后,像这样创建您的Retrofit实例:

MyApi api = Retrofit.Builder()
        .addConverterFactory(gson)
        .baseUrl(API_BASE_URL)
        .build()
        .create(MyApi.class)

其中MyApi是您的Retrofit API接口。

以上是关于如何使用Retrofit 2和Gson来模拟JSON响应“密钥”频繁更改的数据的主要内容,如果未能解决你的问题,请参考以下文章

当列表的各个项目使用Retrofit和Gson的格式不同时,如何解析json列表?

如何使用 Retrofit2 和 GSON 转换器解决“古怪”的 JSON API

如何使用 Gson 和 Retrofit 将类似的 Json 对象转换为 Json 数组

如何使用 gson/retrofit 获取对象数组?

Android实战——Retrofit2的使用和封装

如何在对象 Gson/Retrofit2 中获取字符串