You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Web API的JSON解析为List<Rank>时出现ClassCastException错误求助

解析JSON到List时出现ClassCastException与NullPointerException问题

问题概述

尝试将Web API返回的JSON解析为Rank类的ArrayList时,触发ClassCastException: Cannot cast com.google.gson.JsonPrimitive to com.google.gson.JsonObject,后续还引发了NullPointerException。

错误日志

[19:11:59 WARN]: java.lang.ClassCastException: Cannot cast com.google.gson.JsonPrimitive to com.google.gson.JsonObject
[19:11:59 WARN]:        at java.lang.Class.cast(Unknown Source)
[19:11:59 WARN]:        at com.google.gson.Gson.fromJson(Gson.java:690)
[19:11:59 WARN]:        at me.ma1de.juke.shared.api.APIRequest.getJsonResponse(APIRequest.java:54)
[19:11:59 WARN]:        at me.ma1de.juke.shared.api.APIHandler.request(APIHandler.java:27)
[19:11:59 WARN]:        at me.ma1de.juke.shared.api.APIHandler.request(APIHandler.java:52)
[19:11:59 WARN]:        at me.ma1de.juke.shared.rank.RankHandler.refresh(RankHandler.java:44)
[19:11:59 WARN]:        at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftTask.run(CraftTask.java:71)
[19:11:59 WARN]:        at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
[19:11:59 WARN]:        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
[19:11:59 WARN]:        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
[19:11:59 WARN]:        at java.lang.Thread.run(Unknown Source)
[19:11:59 WARN]: Exception in thread "Craft Scheduler Thread - 48"
[19:11:59 WARN]: org.apache.commons.lang.UnhandledException: Plugin juke-bukkit v1.0-SNAPSHOT generated an exception while executing task 2
        at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:56)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
        at me.ma1de.juke.shared.rank.RankHandler.refresh(RankHandler.java:44)
        at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftTask.run(CraftTask.java:71)
        at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
        ... 3 more

相关代码

RankHandler.refresh()方法

this.ranks = new Gson().fromJson(Juke.INSTANCE.getApiHandler().request("/ranks").getJsonResponse(), new TypeToken<List<Rank>>() {}.getType());

Rank类定义

@Getter @AllArgsConstructor
public class Rank {
    private String id, displayName, prefix, inheritFromId;
    private ChatColor color;
    private List<String> permissions;
    private int weight;
    private boolean staff;
}

待解析JSON内容

[{"id":"default","displayName":"Default","prefix":"","color":"WHITE","permissions":[],"weight":0,"staff":false}]

项目依赖配置

<dependencies>
    <dependency>
        <groupId>org.spigotmc</groupId>
        <artifactId>spigot-api</artifactId>
        <version>1.8.8-R0.1-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.26</version>
    </dependency>

    <dependency>
        <groupId>me.ma1de.juke.shared</groupId>
        <artifactId>Shared</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>31.1-jre</version>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>

    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.10.0</version>
    </dependency>
</dependencies>

已尝试方案

将Gson版本从2.10.1降级到2.8.6,问题未解决。

解决方案

1. 排查APIRequest.getJsonResponse()实现问题

从异常栈可以看出,ClassCastException发生在APIRequest.getJsonResponse()方法内部,说明该方法试图将JsonPrimitive强制转换为JsonObject。核心原因是:

  • API返回的是JSON数组([...]),但getJsonResponse()内部错误地尝试将其解析为JsonObject,导致Gson将响应解析为JsonPrimitive(比如响应是带引号的字符串形式JSON),或者直接解析时类型不匹配。

修复建议:

  • 修改APIRequest.getJsonResponse(),使其返回原始JSON字符串,而非尝试解析为JsonObject;或者返回JsonElement而非强制转换为JsonObject。

2. 调整解析逻辑

如果无法修改APIRequest类,可在调用时先获取原始响应字符串再解析:

// 修改后的refresh方法
String rawResponse = Juke.INSTANCE.getApiHandler().request("/ranks").getRawResponse(); // 假设新增获取原始字符串的方法
if (rawResponse == null || rawResponse.trim().isEmpty()) {
    this.ranks = new ArrayList<>();
    return;
}
this.ranks = new Gson().fromJson(rawResponse, new TypeToken<List<Rank>>() {}.getType());

若getJsonResponse()返回JsonElement,则做类型判断后解析:

JsonElement jsonElement = Juke.INSTANCE.getApiHandler().request("/ranks").getJsonResponse();
if (jsonElement != null && jsonElement.isJsonArray()) {
    this.ranks = new Gson().fromJson(jsonElement, new TypeToken<List<Rank>>() {}.getType());
} else {
    this.ranks = new ArrayList<>();
}

3. 补充Rank类的无参构造函数

Gson默认需要类的无参构造函数来实例化对象,当前Rank类仅用@AllArgsConstructor,会覆盖默认无参构造,可能导致解析失败。添加@NoArgsConstructor:

@Getter
@AllArgsConstructor
@NoArgsConstructor // 添加无参构造
public class Rank {
    private String id, displayName, prefix, inheritFromId;
    private ChatColor color;
    private List<String> permissions;
    private int weight;
    private boolean staff;
}

4. 空值防护

在解析前对响应结果判空,避免触发NullPointerException,如上述代码中对rawResponse或jsonElement的非空判断。


内容的提问来源于stack exchange,提问作者ma1de

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:37:55