Маршалинг JSON и Generics в Java с помощью Spring MVC
Я пытаюсь упорядочить объект JSON в класс-оболочку, содержащий общий объект, а также дополнительную информацию о сигнатуре объекта.
public class Signable<T> {
private T object;
private String signature;
public class Signable() {
generateSignature();
}
/* Getters and setters */
}
Класс wrapper отлично работает до тех пор, пока я создаю его с уже созданным объектом, и он может создать желаемый json
@RequestMapping(value="/test/json/return",method=RequestMethod.GET)
public @ResponseBody Signable<Cart> getTest()
{
Cart cart = new Cart();
// populate cart with OrderItems ...
Signable<Cart> sign = new Signable<Cart>();
sign.setObject(cart);
return sign;
}
который способен генерировать ожидаемый выход
{
"object":{
"orderItems":[
{
"id": "****",
"desc": "asdlfj",
"price": 25.53
}
]
},
"signature":"s9d94f9f9gdfg67d8678g6s87d6f7g6";
}
Какой формат я хочу. Однако при попытке маршалировать тот же json, сгенерированный из Signable, обратно в Signable, я получаю следующую ошибку:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to Cart
По какой-то причине он не может определить, что "объект" в json должен быть сопоставлен с типом Cart (он по умолчанию только привязан к LinkedHashMap), даже если он указан в заголовке метода.
@RequestMapping(value="/test/json/post",method=RequestMethod.POST)
public @ResponseBody Signable<Cart> postTest(@RequestBody Signable<Cart> sign)
Есть ли способ явно указать, какие типы объектов вы хотите сгенерировать из JSON, чтобы вставить вместо общего?
Любая помощь будет принята с благодарностью.
Спасибо.
Ответы
Ответ 1
Проблема здесь в том, что передача соответствующей информации о типе, чтобы заполнить отсутствующую информацию (которая возникает из-за стирания типа Java).
Но самый простой способ - это просто тип подкласса, который вы хотите, чтобы иметь что-то вроде:
class CartSignable extends Signable<Cart> { }
и использовать это вместо создания общего экземпляра; и если это так, информация типа правильно включена (поскольку она хранится в определении класса CartSignable, тогда как Signable имеет только переменную типа!).
Джексон может также получать информацию о типе во время сериализации, но проблема здесь заключается в том, как Spring передаст такую информацию. Поэтому обычно проще просто использовать стиль подклассификации. Обратите внимание, что вы также можете использовать анонимные внутренние классы для подкласса.
Ответ 2
В итоге я расширил
class ListMyObject extends ArrayList<MyObject> { }
спасибо StaxMan - отличная помощь
PS: формат json > [{ "id": "1", "mountain": 2}, { "id": "3", "mountain": 7}]
Ответ 3
Я закончил создание другого класса:
public class JobUpdateList extends ArrayList<JobUpdate> implements Serializable {
//---- Members
private static final long serialVersionUID = 1L;
}
Итак, в контроллере вместо:
public @ResponseBody String setJobStatus(@RequestBody List<JobUpdate> jobUpdates) {
Я сделал это:
public @ResponseBody String setJobStatus(@RequestBody JobUpdateList jobUpdates) {