Я использую API из своего приложения для Android, и все ответы JSON выглядят так:
{
'status': 'OK',
'reason': 'Everything was fine',
'content': {
< some data here >
}
Проблема заключается в том, что все мои POJOs есть status
, reason
поля, так и внутри content
поля является реальным POJO я хочу.
Есть ли способ создать собственный конвертер Gson, чтобы всегда извлекать content
поле, чтобы модификация возвращала соответствующий POJO?
Ответы:
Вы должны написать собственный десериализатор, который возвращает внедренный объект.
Допустим, ваш JSON:
Тогда у вас будет
Content
POJO:Затем вы пишете десериализатор:
Теперь, если вы создадите с
Gson
помощьюGsonBuilder
и зарегистрируете десериализатор:Вы можете десериализовать свой JSON прямо на свой
Content
:Изменить, чтобы добавить из комментариев:
Если у вас есть разные типы сообщений, но все они имеют поле «content», вы можете сделать десериализатор универсальным, выполнив следующие действия:
Вам просто нужно зарегистрировать экземпляр для каждого из ваших типов:
Когда вы вызываете
.fromJson()
тип, переносится в десериализатор, поэтому он должен работать для всех ваших типов.И, наконец, при создании экземпляра Retrofit:
источник
setConverter(new GsonConverter(gson))
вRestAdapter.Builder
класс RetrofitPerson.class
иList<Person>.class
/Person[].class
с отдельным десериализатором?Решение @BrianRoach - правильное решение. Стоит отметить, что в особом случае, когда у вас есть вложенные настраиваемые объекты, для которых требуется настраиваемый объект
TypeAdapter
, вы должны зарегистрировать егоTypeAdapter
с новым экземпляром GSON , иначе второйTypeAdapter
никогда не будет вызван. Это потому, что мы создаем новыйGson
экземпляр внутри нашего настраиваемого десериализатора.Например, если у вас был следующий json:
И вы хотели, чтобы этот JSON был сопоставлен со следующими объектами:
Вам нужно будет зарегистрировать
SubContent
файлTypeAdapter
. Для большей надежности вы можете сделать следующее:а затем создайте его так:
Это можно легко использовать для случая вложенного «содержимого», просто передав новый экземпляр
MyDeserializer
с нулевыми значениями.источник
java.lang.reflect.Type
Немного поздно, но, надеюсь, это кому-то поможет.
Просто создайте следующий TypeAdapterFactory.
и добавьте его в свой конструктор GSON:
или
источник
jsonElement
?. как я естьcontent
,content1
и т.д.Была такая же проблема пару дней назад. Я решил эту проблему, используя класс-оболочку ответа и преобразователь RxJava, что, на мой взгляд, является довольно гибким решением:
Упаковочный:
Пользовательское исключение, которое нужно выбросить, когда статус не в порядке:
Трансформатор Rx:
Пример использования:
Моя тема: Retrofit 2 RxJava - Gson - "Глобальная" десериализация, изменение типа ответа
источник
Продолжая идею Брайана, поскольку у нас почти всегда есть много ресурсов REST, каждый из которых имеет собственный корень, было бы полезно обобщить десериализацию:
Затем, чтобы проанализировать образец полезной нагрузки сверху, мы можем зарегистрировать десериализатор GSON:
источник
Лучшим решением может быть это ..
Затем определите свою службу следующим образом.
источник
Согласно ответу @Brian Roach и @rafakob, я сделал это следующим образом
Json ответ от сервера
Класс обработчика общих данных
Пользовательский сериализатор
Объект Gson
Вызов API
источник
Это то же решение, что и @AYarulin, но предполагается, что имя класса - это имя ключа JSON. Таким образом, вам нужно передать только имя класса.
Затем, чтобы проанализировать образец полезной нагрузки сверху, мы можем зарегистрировать десериализатор GSON. Это проблематично, так как ключ чувствителен к регистру, поэтому регистр имени класса должен соответствовать регистру ключа JSON.
источник
Вот версия Котлина, основанная на ответах Брайана Роуча и А.Ярулина.
источник
В моем случае ключ «содержимого» будет изменяться для каждого ответа. Пример:
В таких случаях я использовал аналогичное решение, указанное выше, но мне пришлось его настроить. Вы можете увидеть суть здесь . Он слишком велик, чтобы размещать его здесь, на SOF.
Используется аннотация,
@InnerKey("content")
а остальной код предназначен для облегчения ее использования с Gson.источник
Не забывайте
@SerializedName
и@Expose
аннотации для всех членов класса и членов внутреннего класса, которые наиболее десериализованы из JSON с помощью GSON.Посмотрите https://stackoverflow.com/a/40239512/1676736
источник
Еще одно простое решение:
источник