Я использую эту библиотеку: 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: class [Ljava.lang.Object; cannot be cast to class java.util.List ([Ljava.lang.Object; and java.util.List are in module java.base of loader 'bootstrap')
В качестве альтернативы args можно опустить (удалить две средние строки и удалить аргумент args для jsonToJava) с тем же эффектом.
Чтение словарей/карт работает нормально, например, этот код печатает «пример», как и ожидалось:
Map<String,Object> fields = (Map<String,Object>)JsonReader.jsonToJava("{\"example\":true}");
for (Map.Entry<String,Object> field : fields.entrySet()) {
System.out.println(field.getKey());
}
Это только массивы, которые я не могу понять, как читать. Документация, которую мне удалось найти для библиотеки, довольно кратка и не показывает пример этого. Отслеживая исходный код, чтобы увидеть, каким должен быть объект, я оказываюсь в функции с именем readArray, где она внутренне использует ArrayList: https://github.com/jdereg/json-io/blob/master/src/main/java/com/cedarsoftware/util/io/JsonParser.java#L280. Похоже, то, что я делаю, должно быть приведено к списку (я также пробовал ArrayList, чтобы быть уверенным).
[Ljava.lang.Object; — это массив Object, поэтому попробуйте выполнить приведение к Object[] и обрабатывать элементы массива по отдельности. Почему это не массив String[]? Поскольку массивы Json могут содержать что угодно, а синтаксический анализатор json не знает тип элементов, пока все они не будут проанализированы (но ему нужно будет где-то хранить их во время синтаксического анализа, поэтому Object — это самый простой в использовании тип — более сложный синтаксический анализатор может проверить тип всех элементов и построить результирующий массив соответствующим образом, но это довольно много усилий для небольшого возврата, поскольку вам все равно нужно знать тип и приведение).
@JoakimDanielson Да, я удалил объект упаковки для упрощения. Насколько я могу судить, json.org не говорит, что сообщение JSON должно начинаться с {. Он также отлично разбирается в nodejs с помощью JSON.parse(str). Но я попробовал, потому что тоже не был уверен, нужно ли его заворачивать, да это и не имело значения. Если я заменю «истинное» значение элемента «пример» второго фрагмента кода, я получу ту же проблему.
@ Томас Спасибо за предложение! Завтра на работе попробую и отчитаюсь.
@ Томас прав. Object[] возвращается массив. Если вы хотите контролировать процесс десериализации и предоставить ожидаемый тип, используйте библиотеку Jackson или Gson.
@ Томас Это работает! Вы хотите опубликовать это как ответ? Я также не уверен, в чем именно разница, особенно потому, что они, похоже, используют ArrayList внутри, поэтому, насколько я понимаю, даже если функция возвращает объект, он должен быть приводимым.




java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class java.util.List
Обратите внимание, что [Ljava.lang.Object представляет тип массива для массивов объектов, поэтому это Object[]. Поскольку массивы json могут содержать что угодно, то есть строки, логические значения, числа, объекты или массивы, и в любой комбинации любой парсер JSON будет иметь 3 варианта:
Object в качестве типа элемента массива. Это приведет к Object[], как в вашем случае.String[]. Если массив содержит что-либо, кроме строк, это, скорее всего, приведет к сбою.String). Однако API не может отразить это, потому что компилятор не знает, что будет содержать json во время выполнения. Следовательно, API может использовать только первые два параметра (во многих библиотеках, таких как Jackon или Gson, оба присутствуют), поэтому пользователю затем придется преобразовать либо массив, либо сами элементы, и в этом случае мало что можно получить, чтобы сделать синтаксический анализатор, который изощрен.Теперь вы, наверное, спросите, почему синтаксический анализатор возвращает Object[] вместо List<Object>. Это решение, принятое разработчиками этой библиотеки, и я могу только догадываться, каковы причины. Однако сам json знает только массивы, поэтому логическим следствием будет использование массивов Java, если не предоставлена другая информация о типе.
«[Ljava.lang.Object представляет тип массива для массивов объектов». Чтобы уточнить, если бы это был просто объект (не массив), ошибка содержала бы Ljava.lang.Object без [? Вот как можно было сказать, в чем дело?
@Luc вывод (тип) для Object будет java.lang.Object, тип для String[] будет [Ljava.lang.String, поэтому [L указывает массив следующего типа (в случае классов или интерфейсов). Дополнительную информацию см. здесь: docs.oracle.com/javase/tutorial/reflect/special/…. В основном результат, который вы получаете, определяется Class.getName().
Чтобы расширить отличный ответ Томаса, вот решение для удобочитаемого 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;
}
Первая строка не похожа на json, вы пробовали
"{\"array\": [\"1.1\",\"1.2\"]}"?