General Gson Сериализация типов API - PullRequest
0 голосов
/ 20 мая 2018

Я работаю с API, который может иметь различные типы для своих атрибутов

Атрибутами могут быть либо идентификаторы, либо объекты

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

Пример:

"platforms": [
        6
    ]

"platforms": [
    {
        "id": 6,
        "name": "PC (Microsoft Windows)",
        "slug": "win",
        "url": "https://www.igdb.com/platforms/win",
        "created_at": 1297639288000,
        "updated_at": 1470063140518,
        "website": "http://windows.microsoft.com/",
        "alternative_name": "mswin"
    }
]

Я работаю с Kotlin и приступил к созданию своего класса Generalizable

data class ObjectType<T>(
        var Id: Long? = null,
        var expand: T? = null
) 

В настоящее время я застрял в создании моего JsonDeserializer,так как он требует возврата типа T, который в моем случае может быть как Int, так и Object.Я попытался заменить T на ObjectType, который работает «лучше», но не может обработать случаи, когда JSON является массивом.

В настоящее время я пытаюсь заставить его работать только с Обобщенным Типом T, как я могу установитьвместо этого введите List>.

Текущая реализация:

class ObjectDeserializer<T> : JsonDeserializer<T> {

    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): T {
        if (json != null) {

            if (json.isJsonArray) {

                val struct: T = Gson().fromJson(json, T::class.java) as T
                return struct
            } else {
                val id = Gson().fromJson(json, Long::class.java)
                //return ObjectType(id, null)
            }

        }

        return T as T
    }
}

Мне бы очень хотелось узнать, как решить эту проблему.

1 Ответ

0 голосов
/ 20 мая 2018

В вашей реализации есть некоторые проблемы и несоответствия.Сначала вы должны убедиться, что десериализованы ObjectType<T>.Таким образом, вы должны объявить класс как:

class ObjectDeserializer<T> : JsonDeserializer<ObjectType<T>>

Также было бы проще предположить, что все параметры не равны нулю:

override fun deserialize(json: JsonElement, typeOfT: Type,
                         context: JsonDeserializationContext): ObjectType<T>

Теперь вы можете использовать typeOfT, которыйна самом деле тип T в JsonDeserializer, а не в ObjectDeserializer.Поэтому это тип ObjectType<T>, который нужно десериализовать.Чтобы перейти к следующему шагу, вам нужно найти фактический тип T:

val objectTypeType = typeOfT as ParameterizedType
val actualTypeOfT = objectTypeType.getActualTypeArguments()[0]

. В качестве следующего шага вам нужно выяснить содержание json.В вашем случае вы никогда не найдете массив, кроме объекта или long:

return if (json.isJsonObject()) {
    val struct: T = context.deserialize(json, actualTypeOfT)
    ObjectType(expand = struct)
} else {
    val id = json.getAsLong()
    ObjectType(Id = id)
}

Здесь вы возвращаете ObjectType экземпляров без какой-либо обработки ошибок, которые, возможно, вам также понадобится добавить.

Затем вы должны предоставить этот десериализатор для Gson по:

registerTypeAdapter(ObjectType::class.java, ObjectDeserializer<Any>())

Всякий раз, когда Gson необходимо десериализовать ObjectType<TheType>, он находитэкземпляр ObjectDeserializer и обеспечивает ObjectType<TheType> как typeOfT до deserialize.

...