Тип общего списка из результата JSON Path - PullRequest
0 голосов
/ 07 ноября 2018

Я хочу сериализовать некоторый JSON, используя POJO, на основе класса Generic, переданного в качестве параметра.

Общий класс должен расширять абстрактный класс, чтобы я мог вызывать некоторые общие методы для получающейся структуры данных.

Пока у меня есть это:

private <T extends TypeInterface> List<DBObject> getDataUsingJsonPath(String path, Class<T> type) {

    TypeRef<List<T>> typeRef = new TypeRef<List<T>>() {};

    Configuration configuration = Configuration
        .builder()
        .mappingProvider(new JacksonMappingProvider())
        .jsonProvider(new JacksonJsonProvider())
        .build();

    List<T> items = JsonPath.using(configuration).parse(jsonString).read(path, typeRef);

    result = items.getAggregations();

Ошибка:

Невозможно создать экземпляр TypeInterface, проблема: абстрактные типы либо должны быть сопоставлены с конкретными типами, иметь собственный десериализатор, или создается с дополнительной информацией о типе

Я пытаюсь сказать, что это расширяет TypeInterface, но фактический класс - это 'type' ... что мне здесь не хватает?

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

Для быстрого решения:

private <T extends TypeInterface> List<DBObject> getDataUsingJsonPath(String path, Class<T> type) {

    Configuration configuration = Configuration
        .builder()
        .mappingProvider(new JacksonMappingProvider())
        .jsonProvider(new JacksonJsonProvider())
        .build();

List<T> items = JsonPath.using(configuration).parse(jsonString).read(path, (Class<List<T>>) new ArrayList<T>().getClass());

Идея состоит в том, чтобы избавиться от TypeRef<List<T>> Это работает, но выдает предупреждение.

0 голосов
/ 08 ноября 2018

Здесь есть несколько хороших ответов, но после некоторого сна я решил вместо этого переместить TypeRef в качестве фактического параметра.

private <T extends TypeInterface> List<DBObject> getDataUsingJsonPath(String path, TypeRef<List<T>> type) {

Затем я могу перебрать результат, как и ожидалось:

List<T> items = JsonPath.using(configuration).parse(responseString).read(path, type);

for(T item : items) {
// do generic TypeInterface stuff here

Я не знаю, является ли это лучшим, наиболее правильным, «универсальным» способом сделать это, но пока все хорошо, и это в основном имеет смысл при чтении кода, который я думаю.

0 голосов
/ 07 ноября 2018

Компилятор скомпилирует new TypeRef<List<T>>() {}; как ссылку на List<T extends TypeInterface>, а не тип элемента, предоставленный type.

Не похоже, что JsonPath поддерживает дальнейшее уточнение typeref путем указания классов. Глядя на исходный код, можно использовать более расширенную библиотеку, такую ​​как guava, со следующими модификациями:

  1. Создайте гуаву TypeToken<T> точно так же, как вы TypeRef<T>, но используйте .where(new TypeParameter<T>() {}, type) для уточнения переменной типа до конечного типа.
  2. Создайте оболочку вокруг нового токена, который предоставляет уточненный тип для JsonPath:

Wrapper:

class TokenRef<T> extends TypeRef<T> {
    private final TypeToken<T> token;

    public TokenRef(TypeToken<T> token) {
        super();
        this.token = token;
    }

    @Override
    public Type getType() {
        return this.token.getType();
    }
}
...