使用 Gson 和 Retrofit 使用多态 json "data: { put_anything_here }"

Consuming polymorphic json "data: { put_anything_here }" with Gson & Retrofit

我不确定多态是否是正确的术语,所以我很抱歉。

我正在使用以下 API:

请求正文:

{
    "user_id": "user_id",
    "command": "submit_document",
}

回应:

{
    "result": "success",
    "code": 200,
    "status": "ok",
    "screen": "documents_rejected", // This is unique for different `data`
    "next_screen": "",
    "message": "Successful",
    "data": {
       // `data` is always a json object with known fields and parameters
    }
}

我有数据 类 准备好用于不同类型的 data 响应,例如:

data class PhoneData(
        @SerializedName("phone_number")
        val phoneNumber: String? = null,
        @SerializedName("phone_status")
        val phoneStatus: String? = null
)

对于 "screen": "phone" 和以下对于另一个屏幕:

data class Data(
        val deepLink: String? = null
)

问题是,一开始,我必须发出以下请求来检索当前屏幕:

{
    "user_id": "user_id",
    "command": "get_current_screen",
}

其中 returns 与上面类似的回复:

{
    "result": "success",
    "code": 200,
    "status": "ok",
    "screen": "main_screen", // Different types of screen types are known.
    "next_screen": "",
    "message": "Successful",
    "data": {
       // `data` is always a json object but the object could contain anything depending on the `screen` type.
    }
}

但数据字段可以包含任何内容,具体取决于 screen

data class SplashScreenData(
        // How do I make this data class combine all other data classes? One ugly approach is to add all the fields from different `data` classes here and use this one only.
)

我发现了用于多态情况的 RuntimeTypeAdapterFactory,但我不确定在 data 对象中没有“类型”之类的字段时如何使它工作(screen 是唯一的,但它在数据对象)。

如果有人有解决方案或能给我指明方向,那将非常有帮助。

                val frameTextReceived: String = frame.readText()
                val jsonObject = JsonParser.parseString(frameTextReceived).asJsonObject
                val type = when (jsonObject.get("type").asString) {
                    TYPE_JOIN_ROOM -> JoinRoom::class.java
                    TYPE_GAME_MOVE -> GameMove::class.java
                    TYPE_DISCONNECT_REQUEST -> DisconnectRequest::class.java
                    else -> BaseModel::class.java
                }
                val payload = gson.fromJson(frameTextReceived, type)

这是我的解决方案,这里我有 type 参数,通过它我可以知道我必须在哪个 class 中反序列化对象,但在你的情况下你有 screen 参数,你可以用这个。