使用 Gson 解析动态 JSON 键值对到 POJO 对象

使用 Gson 解析动态 JSON 键值对到 POJO 对象

本文将针对“使用 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,可以有效地处理 JSON 中动态键的情况。 这种方法避免了创建额外的 POJO 类来包装动态键,简化了代码结构,提高了可读性。 在实际应用中,需要根据具体的 JSON 结构调整 POJO 类的结构,以确保能够正确解析数据。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享