我正在尝试在我的Android项目中使用moshi,但是遇到了一些问题。

这是精简的示例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。这是带有3个字段的ScheduleItem数组:
  • type:字符串标签,用于标识这是
  • 的项目类型
  • item:可以属于EventGameCheckIn
  • schedule_item_groups:一个ScheduleGroup,它是更多列表-ScheduleItems

  • 因此,第一个问题是ScheduleGroup具有ScheduleItems列表,每个项目都可以拥有包含更多项目的自己的ScheduleGroup列表。

    第二个问题是item字段,需要将其实例化为以下三类之一:EventGameCheckIn

    我已经工作了一段时间了,到目前为止,我一次只能工作一个,但不能同时工作。

    这是数据类(我只包括了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_groupsList<ScheduleGroup>进行反序列化的内容。

    我收到一个错误:(这是我之前收到的错误...)

    最佳答案

    我前一段时间想通了,但是我想我可以发表一下我所做的,以防将来对任何人有帮助。

    首先,我创建了一个临时中介类,以在生成通用数据之前保存数据。

    data class ScheduleItem<T>(
        val date: Date,
        val type: String,
        var scheduleGroups: List<ScheduleGroup> = listOf(),
        var item: T
    ) {
        data class ScheduleItemJson(
            val date: Date,
            val type: String,
            val schedule_item_groups: List<ScheduleGroup>? = listOf(),
            val item: Any
        )
    }
    

    然后在适配器中
    @FromJson fun fromJson(item: ScheduleItem.ScheduleItemJson): ScheduleItem<Any> {
        val moshi: Moshi = Moshi.Builder().build()
        val json = moshi.adapter(Map::class.java).toJson(item.item as Map<*, *>)
    
        return ScheduleItem(
            item.date,
            item.type,
            item.schedule_item_groups ?: listOf(),
            when (item.type) {
                ItemType.GAME -> moshi.adapter(GameItem::class.java).fromJson(json)
                ItemType.EVENT -> moshi.adapter(EventItem::class.java).fromJson(json)
                ItemType.CHECK_IN, ItemType.CHECK_OUT ->
                    moshi.adapter(ReservationItem::class.java)
                         .fromJson(json).apply { this!!.type = item.type }
                else -> ScheduleItem.NullItem()
            }!!
        )
    }
    
    when语句创建<T : Item>并将其传递给ScheduleItem构造函数。

    10-08 08:51