当前位置:首页 > 文章列表 > 文章 > java教程 > 动态键JSON解析:Gson实战教程

动态键JSON解析:Gson实战教程

2025-07-31 23:21:32 0浏览 收藏

今日不肯埋头,明日何以抬头!每日一句努力自己的话哈哈~哈喽,今天我将给大家带来一篇《动态键 JSON 解析指南:Gson 实战教程》,主要内容是讲解等等,感兴趣的朋友可以收藏或者有更好的建议在评论提出,我都会认真看的!大家一起进步,一起学习!

使用 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 数据非常简单:

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 数据的关键。

今天关于《动态键JSON解析:Gson实战教程》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

MySQLGROUPBY使用技巧与常见问题MySQLGROUPBY使用技巧与常见问题
上一篇
MySQLGROUPBY使用技巧与常见问题
Java集合原理与优化技巧详解
下一篇
Java集合原理与优化技巧详解
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    306次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    364次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    359次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    327次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    148次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码