在json-io中读取数组:无法将对象强制转换为List

时间:2019-03-18 16:22:04

标签: java arrays json

我正在使用此库:https://github.com/jdereg/json-io

这是我要重现该错误的简化示例:

import com.cedarsoftware.util.io.JsonReader;

Map args = new HashMap();
args.put(JsonReader.USE_MAPS, true);
List<String> a = (List<String>)JsonReader.jsonToJava("[\"1.1\",\"1.2\"]", args);

运行时,抛出:

  

java.lang.ClassCastException:类[Ljava.lang.Object;不能强制转换为类java.util.List([Ljava.lang.Object;和java.util.List在加载程序'bootstrap'的模块java.base中)

或者,args也可以省去(删除中间两行,并删除args的{​​{1}}自变量)。

阅读词典/地图效果很好,例如,此代码按预期输出“ example”:

jsonToJava

只有数组我无法弄清楚如何读取。我已经找到的关于该库的文档非常简洁,并且没有显示此示例。跟踪源代码以查看其应为哪种对象,最后得到一个名为readArray的函数,该函数在内部使用ArrayList:https://github.com/jdereg/json-io/blob/master/src/main/java/com/cedarsoftware/util/io/JsonParser.java#L280。看来我正在做的事情应该可以转换为List(为了确定,我也尝试过ArrayList)。

2 个答案:

答案 0 :(得分:1)

  

java.lang.ClassCastException:类[Ljava.lang.Object;不能转换为类java.util.List

请注意,[Ljava.lang.Object代表对象数组的数组类型,因此它是Object[]。由于JSON数组可以包含任何内容,即字符串,布尔值,数字,对象或数组,并且任何JSON解析器可以任意组合使用3个选项:

  • 使用Object作为数组的元素类型。然后,您的情况将导致Object[]
  • 使用用户提供的某种数组元素类型,即,如果您知道该数组仅包含字符串,则您将告诉解析器它应产生String[]结果。如果该数组包含字符串以外的任何内容,则很可能会失败。
  • 复杂的解析器可能首先收集元素,确定它们的类型,然后尝试使用最特殊的通用类型(如果所有元素都是将是String的字符串)。但是,API无法反映这一点,因为编译器不知道json在运行时将包含什么。因此,API只能使用前两个选项(在许多类似Jackon或Gson的库中都存在),因此用户将不得不强制转换数组或元素本身,在这种情况下,获得的收益很小。如此复杂的解析器。

现在您可能会问为什么解析器返回Object[]而不是List<Object>。这是该库的设计者做出的决定,我只能猜测原因是什么。但是,json本身仅知道数组,因此,如果未提供其他类型信息,则逻辑后果是也将使用Java数组。

答案 1 :(得分:1)

为扩展Thomas的出色答案,以下是人类可读json的解决方案:

将对象列表转换为json:

public String toJSONList(List<Foo> fooList) {
  Map<String, Object> args = new HashMap<>();
  args.put(JsonWriter.PRETTY_PRINT, true); // just to make sure it looks good
  args.put(JsonWriter.TYPE, false); //disable ugly @type properties
  return JsonWriter.objectToJson(fooList, args);
}

它生成具有列表的可读性很好的json:

[
  {
    "id":100,
    "name":"John"
  },
  {
    "id":101,
    "name":"Tirion"
  }
]

将上述json转换回列表

public List<Foo> fromJSONList(String json) {
Map<String, Object> args = new HashMap<>();
args.put(JsonReader.USE_MAPS, true);

JsonReader jsonReader = new JsonReader();
List<Foo> result = new ArrayList<>();
Object[] array = (Object[])JsonReader.jsonToJava(json, args);
for (int i=0; i<array.length; i++) {
  //we need to tell what is the type (remember that we have removed it above?)
  ((Map)array[i]).put("@type", "com.something.model.Foo");
  Foo foo =(Foo)jsonReader.jsonObjectsToJava((JsonObject) array[i]);
  result.add(foo);
}

return result;
}