Универсальный unwrapper для gson

274
06 сентября 2017, 13:22

Суть проблемы: сервер перешёл на новое апи и теперь каждый объект wrap'ит (оборачивает) в структуру

До

{
    "some_field":"some_value"
}

После

{
    "response":/*null или объект / массив объектов из пункта "До"*/,
    "error":/*null или ошибка*/
}

когда 1 из них null - значит второй имеет значение.

Часть (меньшая) объектов имеет адаптеры для десериализации, остальные десереализуются с помощью сгенерированных gson'ом адаптеров. Моя попытка написать универсальный адаптер увенчалась падением с StackOverflowException (понятно что он пытается рекурсивно распарсить каждый раз прыгая из себя в себя).

Мой нерабочий адаптер:

public class DeserializerResponse<T> implements JsonDeserializer<T> {
    private final static String TAG_RESPONSE = "response";
    private final static String TAG_ERROR = "error";
    private Class<T> mCls;
    public DeserializerResponse(Class<T> cls) {
        mCls = cls;
    }
    @Override
    public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        T object = null;
        JsonObject root = json.getAsJsonObject();
        JsonElement responseElement = root.get(TAG_RESPONSE);
        if (!responseElement.isJsonNull()) {
            object = deserializeResponse(responseElement, mCls, context);
        }
        JsonElement errorElement = root.get(TAG_ERROR);
        if (!errorElement.isJsonNull()) {
            String error = errorElement.getAsString();
            throw LoginException.create(error);
        }
        return object;
    }
    protected T deserializeResponse(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        return context.deserialize(json, typeOfT);
    }
}

Данным образом устанавливаю:

@Provides
@Singleton
Gson gson(Map<Type, Object> adapters){
    GsonBuilder builder = new GsonBuilder()
            .setFieldNamingStrategy(new AndroidFieldNamingPolicy())
            .registerTypeAdapterFactory(new TypeAdapterFactory() {
                @Override
                public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
                    Object adapter = adapters.get(type.getType());
                    if (adapter != null) {
                        return TreeTypeAdapter.newFactoryWithMatchRawType(type, adapter).create(gson, type);
                    } else {
                        return TreeTypeAdapter.newFactoryWithMatchRawType(type, new DeserializerResponse<>(type.getRawType())).create(gson, type);
                    }
                }
            })
            .setPrettyPrinting();
    for (Type type : adapters.keySet()){
        builder.registerTypeAdapter(type, adapters.get(type));
    }
    return builder.create();
}

Как решить данную проблему? POJO-wrapper не предлагать. Писать адаптер для каждого класса тоже. Спасибо.

READ ALSO
Чтение файлов из разных потоков

Чтение файлов из разных потоков

Есть Selenium, Chrome DriverЕсть прокси через которое я подключаюсь

311
Android Studio не видит классы

Android Studio не видит классы

После отключения электричества Android Studio перестал воспринимать какие-либо импортируемые классыТеперь весь мой проект выглядит вот так:

330
Не запускается сервер на tomcat на VPS&#39;e

Не запускается сервер на tomcat на VPS'e

Мне нужно сделать клиент-серверное приложение используя RESTful API

272