本文将针对“使用 Gson 解析动态 json 键值对到 POJO 对象时遇到的问题”进行详细讲解。关键在于如何处理 JSON 中键名不固定的部分,即动态键。问题的核心在于 Time Series (5min) 字段下的键是日期时间字符串,无法预先定义。通过修改 TimeSeries 类的结构,使用 map
1. 问题分析
原始代码中,TimeSeries 类定义如下:
public class TimeSeries { @Expose private Map<String, date> dates; public TimeSeries(Map<String,date> dates){ super(); this.dates = dates; } public Map<String, date> getDates() { return dates; } public void setDates(Map<String,date> dates){ this.dates = dates; } }
这段代码的问题在于,它试图将Time Series (5min)直接映射到dates字段,但实际上,Time Series (5min)本身就是一个包含动态键值对的 Map。因此,需要调整 DailyQuote 类,将 Time Series (5min) 直接映射到一个 Map
2. 解决方案
修改 DailyQuote 类的 TimeSeries 字段类型,直接使用 Map
public class DailyQuote { @SerializedName("Meta Data") @Expose private MetaData metaData; @SerializedName("Time Series (5min)") @Expose private Map<String, date> timeSeries; /** * No args constructor for use in serialization */ public DailyQuote() { } /** * @param metaData * @param timeSeries */ public DailyQuote(MetaData metaData, Map<String, date> timeSeries) { super(); this.metaData = metaData; this.timeSeries = timeSeries; } public MetaData getMetaData() { return metaData; } public void setMetaData(MetaData metaData) { this.metaData = metaData; } public Map<String, date> getTimeSeries() { return timeSeries; } public void setTimeSeries(Map<String, date> timeSeries) { this.timeSeries = timeSeries; } }
同时,移除 TimeSeries 类,因为现在不再需要它。
3. 代码示例
以下是修改后的 POJO 类结构:
public class DailyQuote { @SerializedName("Meta Data") @Expose private MetaData metaData; @SerializedName("Time Series (5min)") @Expose private Map<String, DateValue> timeSeries; // Getters and setters... } public class MetaData { @SerializedName("1. Information") @Expose private String _1Information; @SerializedName("2. Symbol") @Expose private String _2Symbol; @SerializedName("3. Last Refreshed") @Expose private String _3LastRefreshed; @SerializedName("4. Interval") @Expose private String _4Interval; @SerializedName("5. Output Size") @Expose private String _5OutputSize; @SerializedName("6. Time Zone") @Expose private String _6TimeZone; // Getters and setters... } public class DateValue { @SerializedName("1. open") @Expose private String _1Open; @SerializedName("2. high") @Expose private String _2High; @SerializedName("3. low") @Expose private String _3Low; @SerializedName("4. close") @Expose private String _4Close; @SerializedName("5. volume") @Expose private String _5Volume; // Getters and setters... }
使用 Gson 解析 JSON 的代码如下:
Gson gson = new Gson(); DailyQuote dailyQuote = gson.fromJson(jsonString, DailyQuote.class); // 访问数据 MetaData metaData = dailyQuote.getMetaData(); Map<String, DateValue> timeSeries = dailyQuote.getTimeSeries(); // 遍历 Time Series if (timeSeries != NULL) { for (Map.Entry<String, DateValue> entry : timeSeries.entrySet()) { String timestamp = entry.getKey(); DateValue dateValue = entry.getValue(); System.out.println("Timestamp: " + timestamp); System.out.println("Open: " + dateValue.get_1Open()); // ... 访问其他数据 } }
4. 注意事项
- Gson 依赖: 确保项目中已经添加了 Gson 依赖。
- 字段命名: @SerializedName 注解必须与 JSON 中的字段名完全一致,包括大小写。
- 类型匹配: POJO 类的字段类型必须与 JSON 中对应的值类型匹配。例如,如果 JSON 中的值是字符串,POJO 类中的字段也应该是 String 类型。
- 空值处理: Gson 默认会将 JSON 中的 null 值映射到 POJO 类的字段中。如果需要自定义空值处理逻辑,可以使用 Gson 的 JsonDeserializer 接口。
5. 总结
通过将 Time Series (5min) 直接映射到 Map
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END