Подтвердить что ты не робот

Дезаминирование общих типов с помощью GSON

У меня есть некоторые проблемы с реализацией Json Deserialization в моем приложении Android (с библиотекой Gson)

Я сделал такой класс

public class MyJson<T>{
    public List<T> posts;
}

И вызов десериализации:

public class JsonDownloader<T> extends AsyncTask<Void, Void, MyJson<T>> {
...
protected MyJson<T> doInBackground(Void... params) {
  ...
    Reader reader = new InputStreamReader(content);
    GsonBuilder gson = new GsonBuilder();
    Type collectionType = new TypeToken<MyJson<T>>() {}.getType();
    result = gson.create().fromJson(reader, collectionType);
  ...
  }
}

Проблема заключается в том, что список result.posts после вызова содержит один массив объектов LinkedTreeMap (с правильными значениями, поэтому проблема - десериализация) вместо объектов MyJson. Когда я использую MyObject вместо T, все работает нормально, а MyObject верен.

Итак, есть ли способ реализовать десериализационный вызов без создания настраиваемого десериализатора?

4b9b3361

Ответ 1

Вы пробовали?

gson.create().fromJson(reader, MyJson.class);

ИЗМЕНИТЬ

После чтения этого сообщения кажется, что вы используете Type правильно. Я считаю, что ваша проблема заключается в использовании T. Вы должны помнить, что с Java существует стирание типа. Это означает, что во время выполнения все экземпляры T заменяются на Object. Поэтому во время выполнения то, что вы проходите, GSON действительно MyJson<Object>. Если вы попробовали это с конкретным классом вместо <T>, я считаю, что это сработает.

Google Gson - список deserialize <class> объект? (общий тип)

Ответ 2

Вы должны указать тип T во время десериализации. Как будет создан ваш List of posts, если Gson не знал, что Type для создания экземпляра? Он не может оставаться навсегда T. Таким образом, вы должны указать тип T как параметр Class.

Теперь предположим, что тип posts был String, вы бы десериализовали MyJson<String> как (я также добавил параметр String json для простоты, вы читали бы из вашего reader, как раньше):

doInBackground(String.class, "{posts: [\"article 1\", \"article 2\"]}");

protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {

    GsonBuilder gson = new GsonBuilder();
    Type collectionType = new TypeToken<MyJson<T>>(){}.getType();

    MyJson<T> myJson = gson.create().fromJson(json, collectionType);

    System.out.println(myJson.getPosts()); // ["article 1", "article 2"]
    return myJson;
}

Аналогично десериализуем MyJson объектов Boolean

doInBackground(Boolean.class, "{posts: [true, false]}");

protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {

    GsonBuilder gson = new GsonBuilder();
    Type collectionType = new TypeToken<MyJson<T>>(){}.getType();

    MyJson<T> myJson = gson.create().fromJson(json, collectionType);

    System.out.println(myJson.getPosts()); // [true, false]
    return myJson;
}

Я предположил, что MyJson<T> для моих примеров как

public class MyJson<T> {

    public List<T> posts;

    public List<T> getPosts() {
        return posts;
    }
}

Итак, если вы искали десериализацию List<MyObject>, вы вызывали бы этот метод как

// assuming no Void parameters were required
MyJson<MyObject> myJson = doInBackground(MyObject.class);

Ответ 3

Таким образом, приведенный выше ответ не помог мне после проб и ошибок, что мой код закончился:

public class AbstractListResponse<T> {
    private List<T> result;

    public List<T> getResult() {
        return this.result;
    }
}

Важной частью здесь является сигнатура метода, включающая '<T> 'слева.

protected <T> AbstractListResponse<T> parseAbstractResponse(String json, TypeToken type) {
    return new GsonBuilder()
            .create()
            .fromJson(json, type.getType());
}

При вызове Gson метод получает TypeToken для общего объекта.

TypeToken<AbstractListResponse<MyDTO>> typeToken = new TypeToken<AbstractListResponse<MyDTO>>() {};
AbstractListResponse<MyDTO> responseBase = parseAbstractResponse(json, typeToken);

И, наконец, TypeToken может использовать MyDTO или даже простой объект, просто MyDTO.