Я пытаюсь использовать moshi в своем проекте Android, но у меня возникают некоторые проблемы.
Вот урезанный образец JSON
{
"data": [
{
"label": "May",
"schedule_items": [
{
"type": "event",
"item": {
"foo": "bar",
"some_prop": 1
},
"schedule_item_groups": [
{
"label": "Friday May 4th",
"schedule_items": [
{
"type": "check_in",
"item": {
"a_different_prop": 15
},
"schedule_item_groups": null
},
{
"type": "game",
"item": {
"yet_another_different_prop": 3598
},
"schedule_item_groups": null
}
]
}
]
}
]
}
]
}
Как видите, это список из ScheduleGroups
, и внутри этого объекта у вас есть метка и schedule_items
. Это массив ScheduleItem
с 3 полями:
type
: Строковая метка, определяющая, какой это тип Предмета.item
: может относиться к классуEvent
,Game
иCheckIn
schedule_item_groups
:ScheduleGroup
, который представляет собой список других -ScheduleItems
Итак, первая проблема заключается в том, что ScheduleGroup
имеет список ScheduleItems
, и каждый элемент может иметь свой собственный список ScheduleGroup
, содержащий больше элементов.
Вторая проблема - это поле item
, его нужно создать как один из трех классов: Event
, Game
, CheckIn
.
Я работаю над этим некоторое время, и пока я могу заставить работать только один, но не оба.
Вот классы данных (я включил только один из Item
классов):
data class ScheduleGroup(
val label: String,
val schedule_items: List<ScheduleItem<Any>>
)
data class ScheduleItem<out T>(
val type: String,
val schedule_item_groups: List<ScheduleGroup>
val item: T
) {
abstract class Item
}
data class Event(
val some_prop: Int,
val foo: String
) : ScheduleItem.Item()
Вот как я заставил работать динамический универсальный класс Item
:
@FromJson
fun fromJson(map: Map<*, *>): ScheduleItem<Any> {
val moshi: Moshi = Moshi.Builder().build()
val type: String = map["type"] as String
val itemJson = moshi.adapter(Map::class.java).toJson(map["item"] as Map<*, *>)
val item = when (type) {
EventType.EVENT -> moshi.adapter(Event::class.java).fromJson(itemJson)
EventType.GAME -> moshi.adapter(Game::class.java).fromJson(itemJson)
EventType.CHECK_IN, EventType.CHECK_OUT ->
moshi.adapter(CheckIn::class.java).fromJson(itemJson)
else -> throw Error("Unknown type was found $type")
}
val scheduleGroupType = Types.newParameterizedType(List::class.java, ScheduleGroup::class.java)
@Suppress("UNCHECKED_CAST")
val scheduleGroupJson = moshi.adapter<List<ScheduleGroup>>(scheduleGroupType)
.toJson(map["schedule_item_groups"] as List<ScheduleGroup>?)
val list: List<ScheduleGroup>? = moshi
.adapter<List<ScheduleGroup>>(scheduleGroupType).fromJson(scheduleGroupJson)
return ScheduleItem(type, list ?: listOf(), item)
}
Он правильно создаст правильный Item
класс, но когда я пытаюсь добавить List<ScheduleGroup>
, я получаю ошибки, и что бы я ни делал, я не могу заставить оба работать.
Редактировать:
Я обновил код, чтобы показать, что я использую, чтобы попытаться десериализовать schedule_item_groups
, который является List<ScheduleGroup>
.
Я получаю сообщение об ошибке: (Это другая ошибка, чем я получал раньше ...)
com.squareup.moshi.JsonDataException: java.lang.IllegalArgumentException: невозможно установить окончательное поле java.lang.String com.roomroster.mobile_android.data.api.schedule.models.ScheduleGroup.label в com.squareup.moshi.LinkedHashTreeMap at $ .data [0] .schedule_items [1]