#java #jackson
#java #джексон
Вопрос:
Например, у меня есть объект-оболочка json
{
"id": 23,
"name": "teset",
"type": "person",
"_data": {
"address": 23432
}
}
мой объект Java будет выглядеть следующим образом
public class Wrapper<D>{
private Integer id;
private String type;
@JsonProperty("_data")
private D data;
...
}
я не могу найти способ заставить сопоставитель объектов сделать это
Wrapper<Person> wrapped = objectMapper.readValue(jsonStream,Wrapper.class);
это не поддерживается, я не смог найти много информации о дженериках в Jackson.
Ответ №1:
В вашем коде есть несколько проблем:
- Основная проблема заключается в том, что вы не указываете желаемый параметризованный тип
Wrapper
в своемreadValue
вызове. Вы можете исправить это, используя (упрощенную форму):Wrapper<Person> wrapped = om.readValue(json, new TypeReference<Wrapper<Person>>() {});
- Кроме того, ваш JSON содержит
name
свойство, которого, по-видимому, нет в вашемWrapper
классе. Он либо у вас есть, но вы его не опубликовали, либо вы можете настроитьObjectMapper
его так, чтобы игнорировать неизвестные свойства:objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Вот пример:
public static class Wrapper<D> {
// making fields public for simplicity,
// use public getters and private fields of course
public Integer id;
public String type;
@JsonProperty("_data")
public D data;
}
public static class Person {
// adding address field as a public int,
// same as above, encapsulate properly in real life
public int address;
}
Затем где-нибудь в основном методе…
ObjectMapper om = new ObjectMapper();
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// your example JSON
String json = "{"id":23,"name":"test","type":"person","_data":"
"{"address":23432}}";
Wrapper<Person> wrapped = om.readValue(
json, new TypeReference<Wrapper<Person>>() {}
);
// printing class/hashCode of the resolved generic type
System.out.println(wrapped.data);
// casting as Person and printing actual property
System.out.println(((Person)wrapped.data).address);
Вывод (аналогично …)
test.Main$Person@dfd3711
23432
Объяснение TypeReference
из документов:
Этот обобщенный абстрактный класс используется для получения полной информации о типе обобщений путем подклассификации; для использования он должен быть преобразован в реализацию ResolvedType (реализованную JavaType из пакета «databind»). Класс основан на идеях из http://gafter.blogspot.com/2006/12/super-type-tokens.html , Дополнительная идея (из предложения, сделанного в комментариях к статье) состоит в том, чтобы потребовать фиктивной реализации Comparable (подойдет любой такой универсальный интерфейс, если он заставляет реализовывать метод с универсальным типом). чтобы убедиться, что аргумент типа действительно задан.
Использование осуществляется путем подклассирования: вот один из способов создания экземпляра ссылки на список общих типов:
TypeReference ref = new TypeReference<List<Integer>>() { };
который может быть передан методам, которые принимают TypeReference, или разрешен с помощью TypeFactory для получения ResolvedType .
Комментарии:
1. большое спасибо за быстрый и подробный ответ, действительно помог мне!