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

Time:11-22

I'm not sure if polymorphic is the right term to use so my apologies.

I'm working with the following API:

Request body:

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

Response:

{
    "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
    }
}

I have data classes ready for different types of data responses like:

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

for "screen": "phone" and the following for another screen:

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

The problem is, at the start, I have to make the following request to retrieve the current screen:

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

which returns a similar response as above:

{
    "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.
    }
}

but the data field could contain anything depending on the 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.
)

I found about the RuntimeTypeAdapterFactory for polymorphic cases but am not sure how to make it work when there's no "type" like field within the data object (screen is unique but it's outside the data object).

It would be very helpful if someone has a solution or could point me in a direction.

CodePudding user response:

                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)

This is my solution, here I have type parameter by which I can know in which class I have to deserialize the object but in your case you have screen parameter, you can use this.

  • Related