您的位置:首页 >Gson解析JSON数组转List方法详解
发布于2026-04-16 阅读(0)
扫一扫,手机访问

本文详解 Gson 反序列化时出现 ClassCastException: Cannot cast JsonPrimitive to JsonObject 的根本原因,重点解决 ChatColor 类型不匹配、缺失字段及 JSON 结构误判等问题,并提供可直接复用的修复方案。
本文详解 Gson 反序列化时出现 `ClassCastException: Cannot cast JsonPrimitive to JsonObject` 的根本原因,重点解决 `ChatColor` 类型不匹配、缺失字段及 JSON 结构误判等问题,并提供可直接复用的修复方案。
该错误看似发生在 Gson 解析阶段(fromJson(...)),实则根源在于 Java 类型定义与 JSON 数据结构严重不一致。从你提供的 JSON 示例 ["{...}"] 可知,API 返回的是标准 JSON 数组,但 Gson 在尝试将其中某个元素(如字符串 "WHITE")强制转为 JsonObject 时失败——这通常意味着 Gson 正在解析一个本应是对象(JsonObject)的位置,却遇到了原始值(JsonPrimitive),典型诱因有以下三点:
ChatColor color 字段类型失配
JSON 中 "color": "WHITE" 是字符串字面量,而你的 Rank 类中声明为 ChatColor(Spigot 的枚举类)。Gson 默认无法自动将字符串 "WHITE" 映射为 ChatColor.WHITE,若未注册自定义 TypeAdapter,Gson 会尝试以泛型方式解析该字段,最终因类型擦除和内部反射逻辑错乱,触发 JsonPrimitive → JsonObject 的非法强转。
inheritFromId 字段缺失且无默认值
JSON 示例中未包含 "inheritFromId" 字段,而 Rank 构造器为全参 @AllArgsConstructor,Lombok 会生成要求所有字段非 null 的构造函数。Gson 在反序列化时若找不到对应键,将传入 null,导致后续构造失败或空指针异常(日志末尾的 NullPointerException 已佐证)。
JSON 响应体可能非纯数组(隐藏陷阱)
虽然你确认返回的是 [{"id":"default",...}],但需严格验证 getJsonResponse() 方法是否始终返回合法 JSON 数组字符串。常见错误包括:
// 创建 Gson 实例时注入适配器
Gson gson = new GsonBuilder()
.registerTypeAdapter(ChatColor.class, new JsonDeserializer<ChatColor>() {
@Override
public ChatColor deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonNull()) return null;
String colorName = json.getAsString().toUpperCase();
try {
return ChatColor.valueOf(colorName);
} catch (IllegalArgumentException e) {
// 处理未知颜色名,例如回退到 WHITE 或抛出定制异常
return ChatColor.WHITE;
}
}
})
.create();@Getter
@NoArgsConstructor // 必须添加无参构造器,Gson 反序列化必需
@AllArgsConstructor(access = AccessLevel.PRIVATE) // 私有全参构造,避免外部滥用
public class Rank {
private String id;
private String displayName;
private String prefix;
private String inheritFromId; // 改为 String 类型(更安全),或设为 @Nullable
private ChatColor color;
private List<String> permissions;
private int weight;
private boolean staff;
// 若需保留继承关系,可添加带默认值的构造器
public Rank(String id, String displayName, String prefix, String inheritFromId,
ChatColor color, List<String> permissions, int weight, boolean staff) {
this.id = id;
this.displayName = displayName;
this.prefix = prefix;
this.inheritFromId = inheritFromId != null ? inheritFromId : ""; // 安全默认值
this.color = color;
this.permissions = permissions != null ? permissions : new ArrayList<>();
this.weight = weight;
this.staff = staff;
}
}public void refresh() {
String jsonResponse = Juke.INSTANCE.getApiHandler().request("/ranks").getJsonResponse();
// 强制校验 JSON 合法性(防御性编程)
if (jsonResponse == null || jsonResponse.trim().isEmpty()) {
throw new IllegalStateException("API returned empty or null JSON response");
}
try {
// 使用预配置的 Gson 实例
Type listType = new TypeToken<List<Rank>>() {}.getType();
this.ranks = gson.fromJson(jsonResponse, listType);
// 可选:验证解析结果
if (this.ranks == null) {
throw new IllegalStateException("Gson failed to parse JSON into List<Rank>");
}
} catch (JsonSyntaxException e) {
throw new RuntimeException("Invalid JSON syntax in /ranks response: " + jsonResponse, e);
} catch (JsonParseException e) {
throw new RuntimeException("Failed to parse Rank objects: " + e.getMessage(), e);
}
}通过以上三步改造,即可彻底解决 ClassCastException,并构建出稳定、可维护的 JSON 反序列化流程。
上一篇:香香漫画免费入口及官网地址
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9