使用 Gson 解析包含动态键的 JSON 数据到 POJO

使用 gson 解析包含动态键的 json 数据到 pojo

本文档旨在帮助开发者理解如何使用 Gson 库解析包含动态键的 JSON 数据,并将其映射到 Java POJO (Plain Old Java Object) 类中。我们将通过一个股票行情数据的例子,详细介绍如何正确地定义 POJO 类结构,以及如何使用 Gson 进行反序列化,解决Retrofit2返回null的问题。

理解 JSON 结构与 POJO 设计

在处理包含动态键的 JSON 数据时,关键在于理解数据的结构,并设计合适的 POJO 类来映射它。例如,考虑以下 JSON 结构:

{    "Meta Data": {        "1. Information": "Intraday (5min) open, high, low, close prices and volume",        "2. Symbol": "IBM",        "3. Last Refreshed": "2022-10-26 19:40:00",        "4. Interval": "5min",        "5. Output Size": "Compact",        "6. Time Zone": "US/Eastern"    },    "Time Series (5min)": {        "2022-10-26 19:40:00": {            "1. open": "135.0600",            "2. high": "135.0700",            "3. low": "135.0400",            "4. close": "135.0700",            "5. volume": "500"        },        "2022-10-26 19:05:00": {            "1. open": "135.3500",            "2. high": "135.3500",            "3. low": "135.3500",            "4. close": "135.3500",            "5. volume": "106"        }    }}

在这个例子中,”Time Series (5min)” 下的键是动态的,代表不同的时间戳。我们需要使用 Map 来映射这种结构,其中 String 是时间戳,Date 是包含股票数据的 POJO 类。

POJO 类定义

以下是对应的 POJO 类定义:

import com.google.gson.annotations.Expose;import com.google.gson.annotations.SerializedName;import java.util.Map;public class DailyQuote {    @SerializedName("Meta Data")    @Expose    private MetaData metaData;    @SerializedName("Time Series (5min)")    @Expose    private Map timeSeries; // 修改为 Map    public DailyQuote() {    }    public DailyQuote(MetaData metaData, Map timeSeries) {        this.metaData = metaData;        this.timeSeries = timeSeries;    }    public MetaData getMetaData() {        return metaData;    }    public void setMetaData(MetaData metaData) {        this.metaData = metaData;    }    public Map getTimeSeries() {        return timeSeries;    }    public void setTimeSeries(Map timeSeries) {        this.timeSeries = timeSeries;    }}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;    public MetaData() {    }    public MetaData(String _1Information, String _2Symbol, String _3LastRefreshed, String _4Interval, String _5OutputSize, String _6TimeZone) {        this._1Information = _1Information;        this._2Symbol = _2Symbol;        this._3LastRefreshed = _3LastRefreshed;        this._4Interval = _4Interval;        this._5OutputSize = _5OutputSize;        this._6TimeZone = _6TimeZone;    }    public String get1Information() {        return _1Information;    }    public void set1Information(String _1Information) {        this._1Information = _1Information;    }    public String get2Symbol() {        return _2Symbol;    }    public void set2Symbol(String _2Symbol) {        this._2Symbol = _2Symbol;    }    public String get3LastRefreshed() {        return _3LastRefreshed;    }    public void set3LastRefreshed(String _3LastRefreshed) {        this._3LastRefreshed = _3LastRefreshed;    }    public String get4Interval() {        return _4Interval;    }    public void set4Interval(String _4Interval) {        this._4Interval = _4Interval;    }    public String get5OutputSize() {        return _5OutputSize;    }    public void set5OutputSize(String _5OutputSize) {        this._5OutputSize = _5OutputSize;    }    public String get6TimeZone() {        return _6TimeZone;    }    public void set6TimeZone(String _6TimeZone) {        this._6TimeZone = _6TimeZone;    }}public class Date {    @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;    public Date() {    }    public Date(String _1Open, String _2High, String _3Low, String _4Close, String _5Volume) {        this._1Open = _1Open;        this._2High = _2High;        this._3Low = _3Low;        this._4Close = _4Close;        this._5Volume = _5Volume;    }    public String get1Open() {        return _1Open;    }    public void set1Open(String _1Open) {        this._1Open = _1Open;    }    public String get2High() {        return _2High;    }    public void set2High(String _2High) {        this._2High = _2High;    }    public String get3Low() {        return _3Low;    }    public void set3Low(String _3Low) {        this._3Low = _3Low;    }    public String get4Close() {        return _4Close;    }    public void set4Close(String _4Close) {        this._4Close = _4Close;    }    public String get5Volume() {        return _5Volume;    }    public void set5Volume(String _5Volume) {        this._5Volume = _5Volume;    }    @Override    public String toString() {        return "List:{" +                "Open='" + get1Open() + ''' +                ", High='" + get2High() + ''' +                ", Low='" + get3Low() + ''' +                ", Close='" + get4Close() + ''' +                ", Volume='" + get5Volume();    }}

注意 DailyQuote 类中 timeSeries 字段的类型是 Map,而不是 TimeSeries。 TimeSeries 类不再需要,直接使用 Map 即可。

使用 Gson 反序列化 JSON

使用 Gson 反序列化 JSON 数据非常简单:

Find JSON Path Online Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 30 查看详情 Find JSON Path Online

import com.google.gson.Gson;public class Main {    public static void main(String[] args) {        String json = "{n" +                "    "Meta Data": {n" +                "        "1. Information": "Intraday (5min) open, high, low, close prices and volume",n" +                "        "2. Symbol": "IBM",n" +                "        "3. Last Refreshed": "2022-10-26 19:40:00",n" +                "        "4. Interval": "5min",n" +                "        "5. Output Size": "Compact",n" +                "        "6. Time Zone": "US/Eastern"n" +                "    },n" +                "    "Time Series (5min)": {n" +                "        "2022-10-26 19:40:00": {n" +                "            "1. open": "135.0600",n" +                "            "2. high": "135.0700",n" +                "            "3. low": "135.0400",n" +                "            "4. close": "135.0700",n" +                "            "5. volume": "500"n" +                "        },n" +                "        "2022-10-26 19:05:00": {n" +                "            "1. open": "135.3500",n" +                "            "2. high": "135.3500",n" +                "            "3. low": "135.3500",n" +                "            "4. close": "135.3500",n" +                "            "5. volume": "106"n" +                "        }n" +                "    }n" +                "}";        Gson gson = new Gson();        DailyQuote dailyQuote = gson.fromJson(json, DailyQuote.class);        System.out.println("Meta Data: " + dailyQuote.getMetaData().get2Symbol());        System.out.println("Time Series: " + dailyQuote.getTimeSeries().toString());    }}

这段代码首先创建了一个 Gson 实例,然后使用 fromJson() 方法将 JSON 字符串转换为 DailyQuote 对象。

Retrofit 集成

在 Retrofit 中使用 Gson,你需要确保 Gson Converter Factory 被正确配置。以下是一个简单的 Retrofit 接口定义:

import retrofit2.Call;import retrofit2.http.GET;public interface ApiService {    @GET("your_api_endpoint")    Call getDailyQuote();}

确保你的 Retrofit 客户端配置中包含了 Gson Converter Factory:

import retrofit2.Retrofit;import retrofit2.converter.gson.GsonConverterFactory;public class RetrofitClient {    private static Retrofit retrofit;    private static final String BASE_URL = "your_base_url";    public static Retrofit getRetrofitInstance() {        if (retrofit == null) {            retrofit = new Retrofit.Builder()                    .baseUrl(BASE_URL)                    .addConverterFactory(GsonConverterFactory.create())                    .build();        }        return retrofit;    }}

然后,你可以像这样使用 Retrofit 获取数据:

import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;public class NetworkCall {    public static void main(String[] args) {        ApiService apiService = RetrofitClient.getRetrofitInstance().create(ApiService.class);        Call call = apiService.getDailyQuote();        call.enqueue(new Callback() {            @Override            public void onResponse(Call call, Response response) {                if (response.isSuccessful()) {                    DailyQuote dailyQuote = response.body();                    System.out.println("Meta Data: " + dailyQuote.getMetaData().get2Symbol());                    System.out.println("Time Series: " + dailyQuote.getTimeSeries().toString());                } else {                    System.out.println("Request failed: " + response.message());                }            }            @Override            public void onFailure(Call call, Throwable t) {                System.out.println("Request failed: " + t.getMessage());            }        });    }}

注意事项

字段命名: 确保 POJO 类的字段名与 JSON 中的键名一致,或者使用 @SerializedName 注解来指定映射关系。数据类型: 选择合适的数据类型来映射 JSON 中的值。例如,数字可以使用 int、double 或 String,布尔值可以使用 boolean,数组可以使用 List。Gson 配置: 可以自定义 Gson 实例,例如设置日期格式、处理 null 值等。异常处理: 在反序列化过程中,可能会出现异常,例如 JSON 格式错误、数据类型不匹配等。需要进行适当的异常处理。

总结

通过本文,你学习了如何使用 Gson 解析包含动态键的 JSON 数据,并将其映射到 POJO 类中。关键在于理解 JSON 结构,并使用 Map 或自定义 POJO 类来映射动态键。结合 Retrofit,你可以轻松地从 API 获取数据,并将其转换为 Java 对象进行处理。 记住,良好的 POJO 设计和适当的 Gson 配置是成功解析 JSON 数据的关键。

以上就是使用 Gson 解析包含动态键的 JSON 数据到 POJO的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/249972.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
长安汽车深蓝S05首发加入荣耀车联 应用无缝流转
上一篇 2025年11月4日 05:01:17
鸿蒙版企业微信一次更新十余项功能,沟通协作、客户管理再升级!
下一篇 2025年11月4日 05:01:22

相关推荐

  • safari浏览器如何开启画中画模式播放视频_safari浏览器画中画模式开启方法

    如果您在观看网页视频时希望同时进行其他操作,可以启用 Safari 浏览器的画中画模式,让视频以浮动小窗形式继续播放。此功能支持大多数主流视频网站,如 YouTube、优酷等。 本文运行环境:MacBook Air,macOS Sonoma 一、通过视频右键菜单开启画中画 此方法适用于正在播放的视频…

    2026年9月23日
    000
  • FlexClip如何用于在线AI视频制作?快速创建云端AI视频的技巧

    FlexClip如何用于在线AI视频制作?快速创建云端AI视频的技巧FlexClip如何用于在线AI视频制作?快速创建云端AI视频的技巧FlexClip如何用于在线AI视频制作?快速创建云端AI视频的技巧FlexClip如何用于在线AI视频制作?快速创建云端AI视频的技巧

    FlexClip通过AI脚本生成、文本转视频、AI配音与图片生成等智能工具,实现从文案到成片的高效制作。其亮点在于一站式云端操作、强大内容生成力、素材库丰富、易用性与专业性兼备。用户可通过个性化修改、原创素材融入、精细剪辑及多轮迭代提升视频独特性,同时应对AI理解偏差、素材同质化、情感表达局限等挑战…

    2026年9月23日 用户投稿
    000
  • mysql怎么添加降序索引 mysql创建排序索引的语法详解

    mysql怎么添加降序索引 mysql创建排序索引的语法详解mysql怎么添加降序索引 mysql创建排序索引的语法详解mysql怎么添加降序索引 mysql创建排序索引的语法详解mysql怎么添加降序索引 mysql创建排序索引的语法详解

    mysql从8.0版本开始支持降序索引,通过在列名后添加desc关键字创建,例如create index idx_order_date_desc on orders (order_date desc);。1. 降序索引优化了order by column desc查询的性能,避免文件排序;2. 升序…

    2026年9月23日 用户投稿
    100
  • Java中使用栈验证JSON字符串结构:深入理解与实践

    本文探讨了在Java中利用栈验证JSON字符串结构的核心原理与常见陷阱。我们将分析一种初始实现中处理引号、转义字符及字符串内部结构字符的不足,并提供一个更健壮的栈基方法,以准确判断JSON的括号、方括号和引号是否平衡,同时纠正关于不完整JSON片段有效性的常见误解。 1. JSON结构与验证的重要性…

    2026年9月23日
    100
  • mysql索引类型有哪些 mysql创建不同索引的方法对比

    mysql索引类型有哪些 mysql创建不同索引的方法对比mysql索引类型有哪些 mysql创建不同索引的方法对比mysql索引类型有哪些 mysql创建不同索引的方法对比mysql索引类型有哪些 mysql创建不同索引的方法对比

    mysql支持多种索引类型,选择合适的索引类型可提升数据库性能。1.b-tree索引适用于等值、范围查询和排序,是innodb和myisam的默认索引;2.hash索引仅适合等值查询,不支持范围和排序,memory引擎支持显式创建;3.fulltext索引用于文本搜索,适合关键词查找;4.空间索引(…

    2026年9月23日 用户投稿
    000
  • Tableau的AI混合工具如何操作?生成智能数据可视化的实用指南

    Tableau的AI混合工具通过自然语言查询、自动解释和预测模型,降低数据分析门槛,帮助非技术用户快速获取洞察。首先,Ask Data支持用日常语言提问,自动生成可视化图表,显著提升数据探索效率;其次,Explain Data利用机器学习分析异常点,揭示潜在影响因素,将“是什么”转化为“为什么”;再…

    2026年9月23日
    000
  • mysql安装完成如何事件 mysql定时任务设置教程

    mysql安装完成如何事件 mysql定时任务设置教程mysql安装完成如何事件 mysql定时任务设置教程mysql安装完成如何事件 mysql定时任务设置教程mysql安装完成如何事件 mysql定时任务设置教程

    要使用mysql的事件调度器设置定时任务,首先需开启事件调度器,其次创建定时事件,再查看管理事件,最后注意权限与时间格式等问题。具体步骤如下:1. 开启事件调度器:通过命令或配置文件启用;2. 创建事件:使用create event定义执行频率与sql操作;3. 管理事件:可查看、修改或删除已有事件…

    2026年9月23日 用户投稿
    100
  • OpenAI 与微软达成重磅交易:股权结构再变,投资者面临稀释风险

    据《金融时报》披露,OpenAI 近期完成了一系列关键性交易,使其股权架构日趋复杂,同时也加剧了投资者对未来收益前景的担忧。在这些新协议推动下,OpenAI 的估值已飙升至5000亿美元,跃居全球最具价值的未上市企业之列。这一惊人估值的背后,是公司与英伟达和AMD两家芯片巨头达成的数十亿美元合作协议…

    2026年9月23日
    000
  • NS2版《无主之地4》突遭延期!预购将取消

    《无主之地4》现可提前购入,使用金币叠加限时优惠券后,标准版仅需244.5元(共节省 ¥53.5);超级豪华版为457.4元(总计优惠 ¥100.6)。 原计划于10月3日发布的《无主之地4》Nintendo Switch 2版本已确认延期。Gearbox Entertainment最新发布公告称,…

    2026年9月23日
    200
  • 如何在mysql中优化多表JOIN查询

    答案:优化MySQL多表JOIN需创建关联字段索引、提前过滤数据、选择合适JOIN类型与表序、利用EXPLAIN分析执行计划,并定期更新统计信息以提升查询效率。 在MySQL中优化多表JOIN查询,关键在于减少数据扫描量、提升连接效率,并合理利用索引和执行计划。以下是一些实用的优化策略。 1. 确保…

    2026年9月23日
    300
  • WooCommerce 购物车联动:实现赠品自动添加与移除的专业指南

    本文提供了一份关于在 woocommerce 中实现自动赠品系统的全面指南。它解决了在程序化添加产品时常见的 `woocommerce_add_to_cart` 递归问题,并提供了一个使用自定义购物车项元数据来管理关联赠品的健壮解决方案,确保赠品能与特定主产品同步添加和移除。 引言 在电子商务中,为…

    2026年9月23日
    500
  • MySQL安装需要哪些硬件配置要求?

    MySQL安装需要哪些硬件配置要求?MySQL安装需要哪些硬件配置要求?MySQL安装需要哪些硬件配置要求?MySQL安装需要哪些硬件配置要求?

    mysql的硬件配置需根据应用场景和负载决定,生产环境应重点考虑磁盘i/o、内存、cpu和网络。1. cpu:oltp场景多核心更重要,olap则更依赖主频和缓存;2. 内存:buffer pool越大越好,但需避免过度分配导致swap使用;3. 磁盘i/o:ssd是标配,nvme ssd和raid…

    2026年9月23日 用户投稿
    200
  • 如何在Procreate中使用AI导出图片?保存高质量图像的正确方法

    Procreate无内置AI导出功能,但可通过导出高质量图像(如PSD、TIFF、PNG)供外部AI工具优化;选择格式需根据用途,PSD适合协作,TIFF用于印刷,PNG支持透明背景,JPEG慎用以避免压缩损失;画布应高DPI创建,色彩配置优先sRGB,印刷时后期转CMYK更精准。 ☞☞☞AI 智能…

    2026年9月23日
    100
  • linux如何优雅的关机

    优雅关机的三大法宝:拔电源、shutdown、poweroff 及其对硬件和数据的影响 在讨论关机方法之前,先了解一下机械硬盘的内部结构。 那固态硬盘SSD呢? FTL工作示意图。FTL表对SSD至关重要,如果在FTL写回Flash之前突然断电,内存数据丢失,FTL表也将丢失。因此,高端SSD和服务…

    2026年9月23日
    100
  • PHP自定义函数:创建与使用 prev_id() 函数的实践指南

    本文旨在指导读者如何定义和实现自定义PHP函数,以解决“Call to undefined function”错误。通过 prev_id() 函数的创建示例,详细阐述了函数的基本语法、参数传递、返回值以及在实际应用(如数据库查询)中的集成方法,并提供了关键注意事项,帮助开发者编写模块化、可维护的代码…

    2026年9月23日
    100
  • 四种获取fasta序列长度的方法

    在处理fasta序列时,我们常常需要知道每条序列的长度。今天小编将与大家分享四种获取fasta序列长度的方法。 一、使用awk 以下是使用awk获取fasta序列长度的代码: awk ‘/^>/{if (l!=””) print l; print; l=0; next}{l+=length($…

    2026年9月23日
    200
  • VSCode如何实现代码版本对比 VSCode Git差异对比的高效使用方法

    vscode通过scm视图直接对比工作区与head的差异;2. 点击已暂存文件可查看暂存区与head的差异;3. 通过命令面板、scm历史记录或右键菜单可对比任意版本或文件;4. 差异视图支持并排和内联模式,并提供跳转导航;5. 时间线视图可追溯文件级提交历史并对比各版本;6. gitlens扩展增…

    2026年9月23日
    600
  • mysql索引怎么用 mysql创建索引提高查询性能方法

    mysql索引怎么用 mysql创建索引提高查询性能方法mysql索引怎么用 mysql创建索引提高查询性能方法mysql索引怎么用 mysql创建索引提高查询性能方法mysql索引怎么用 mysql创建索引提高查询性能方法

    索引是mysql中提高查询性能的关键工具,它类似于书籍目录,可快速定位数据。创建索引主要使用create index或alter table语句,例如:create index idx_email on users (email); 或 alter table users add index idx…

    2026年9月23日 用户投稿
    100
  • Java中基于栈验证JSON字符串结构有效性的方法

    本文探讨了在Java中利用栈(Stack)数据结构验证JSON字符串结构有效性的方法。我们将分析一个常见的基于栈的实现示例,指出其在处理字符串内部字符、引号平衡以及转义字符方面的潜在缺陷。文章将提供一个改进的解决方案,并强调此方法主要用于结构匹配,而非完整的JSON语法验证,同时建议生产环境中使用专…

    2026年9月23日
    200
  • 快手极速版官方网页版地址_快手极速版App下载官网首页

    快手极速版官方网页版地址在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来快手极速版官方网页版地址及App下载相关信息,感兴趣的网友一起随小编来瞧瞧吧! https://www.kuaishou.com/ 1、小步骤内容。进入官网后可直接浏览平台首页推荐内容,涵盖生活记录、才艺展示等多个领域…

    2026年9月23日
    300

发表回复

登录后才能评论
关注微信