尝试解析 JSONArray 时出现 ClassCastException

ClassCastException when trying to parse a JSONArray

当尝试使用 json.simple 库解析以下 JSON 字符串时:

[
    {"id" : "6d7662a9.f8ba04"},
    {"id" : "2da98cc2.145ba4"},
    {"id" : "45492640.a17d68"}
]

我得到这个异常:

java.lang.ClassCastException: org.json.simple.JSONArray cannot be cast to org.json.simple.JSONArray

我就是这样做的:

JSONArray json = (JSONArray) new JSONParser().parse(jsonString);

JSON 字符串是一个数组,所以不确定为什么会抛出该异常。

这里有几个类似的问题,但在他们的情况下,他们试图将 JSONObject 转换为 JSONArray 因此抛出异常是有道理的,但在这种情况下,它看起来正确。

----------------编辑----------------

我加了一行打印对象的class,像这样:

Object json = new JSONParser().parse(jsonString);
System.out.println(json.getClass());

打印以下行:

class org.json.simple.JSONArray

在下一行,如果:

if(json instanceof JSONArray) {
    System.out.println("This is a JSONArray");
}

但它不访问 if,所以它真的很奇怪,因为首先我检查对象是一个 JSONArray 但它不打印 "This is a JSONArray"

应该是

    Object obj = new JSONParser().parse(jsonString);
    JSONArray json = new JSONArray();
json.add(obj);

你说你得到了这个:

java.lang.ClassCastException: org.json.simple.JSONArray cannot be cast 
    to org.json.simple.JSONArray

请注意,完全限定的 class 名称看起来完全相同。如果该消息被准确转录,并且名称 相同 1,则意味着您有两个版本的 JSONArray class 加载到你的 JVM 中!

这在应用程序或框架具有多个 class 加载器的 JVM 中是可能的,并且您已设法在多个 class 加载器中加载 class。例如,如果您在 Web 容器的共享库目录和 Web 应用程序的 WAR 文件中都有 JSON 库 JAR 文件,则可能会发生这种情况。

问题是 class 的运行时类型由 classes FQN 和 classloader 标识。在不同的 class 加载器中加载的具有相同 FQN 的两个 class 是不同的类型,即使字节码是相同的。这意味着它们与赋值不兼容,这会导致奇怪的(但正确的!)class 转换失败。

解决方案:

  1. 查看执行平台上的 Web 容器文件树,找到 JSON JAR 文件的多个副本。
  2. 从共享库目录或所有 WAR 文件中删除有问题的副本。

1 - 一个非常晦涩的替代解释是名称由于 "homoglyphs" 看起来相同但实际上不同。但在这种情况下,我认为我们可以认为这种解释不可信。