I need to parse the list of `data class` into a `j...
# ktor
k
I need to parse the list of
data class
into a
json array
while sending the response. I am converting the model’s content to
JsonObject
and then adding the object to
JsonArray
. Can someone please suggest a better approach?
Copy code
@Serializable
data class MyModel(
    val name: String,
    val number: String
)
Copy code
val list = arrayListOf<MyModel>()
repeat(5) {
    list.add(
        MyModel(
            name = UUID.randomUUID().toString(),
            number = UUID.randomUUID().toString()
        )
    )
}

val jsonArray = buildJsonArray {
    list.forEach {
        val obj = buildJsonObject {
            put("name", it.name)
            put("number", it.number)
        }
        add(obj)
    }
}

call.respond(buildJsonObject {
    put("pageSize", 10)
    put("list", jsonArray)
})
a
You can just respond with a list of your objects:
Copy code
val list = mutableListOf<MyModel>()
repeat(5) {
    list.add(
        MyModel(
            name = UUID.randomUUID().toString(),
            number = UUID.randomUUID().toString()
        )
    )
}

call.respond(list)
k
Yes, for sending a
JsonArray
we can directly use
call.respond(list)
. But can you please help with when we need to send a
JsonObject
with
JsonArray
as mentioned in the above snippet
a
Sorry, I don't understand your question. Can you please rephrase it?
k
I am trying to serve a paginated request which will respond a
JsonObject
Copy code
{
    "key" : "some_key",
    "pageSize" : 10,
    "notifications" : [
        // notifications list
    ]
}
I have a
data class
NotificationDto. I need to send
List<NotificationDto>
as
notifications
array in my response but I couldn’t find any method to directly convert my model list into
JsonArray
. To achieve the similar results for another API, I have done this:
Copy code
val jsonArray = buildJsonArray {
    users.forEach {
        val obj = buildJsonObject {
            put("userId", it.userId)
            put("name", it.name)
            put("photoUrl", it.photoUrl)
            put("username", it.username)
            put("isFollowedBySelf", followings[it.userId].isTrue())
        }
        add(obj)
    }
}
respond(buildJsonObject {
    put("key", nextKey)
    put("pageSize", jsonArray.size)
    put("users", jsonArray)
})
In the above code, I have manually created the fields and adding them to the
JsonArray
. How can we send a List of
data class
without converting each field manually? This is the code I am trying with:
Copy code
val notificationsDtoList = mutableListOf<NotificationDto>()
notifications.forEach {
    notificationsDtoList.add(
        NotificationDto(
            userId = it.actionTakenBy,
            type = it.type,
            postId = it.postId,
            postImageUrl = it.postImageUrl,
            timeStamp = it.timeStamp,
            username = usersMap[it.actionTakenBy]?.username,
            photoUrl = usersMap[it.actionTakenBy]?.photoUrl
        )
    )
}
val nextKey = if (notifications.size == pageSize) {
    notifications[pageSize - 1].timeStamp
} else -1

call.respond(buildJsonObject {
    put("key", nextKey)
    put("pageSize", notifications.size)
    putJsonArray("notifications", notificationsDtoList) // Compilation error here because notificationsDtoList is not a JsonArray
})
This is the result I need to achieve:
Copy code
{
  "key": "some_key",
  "pageSize": 10,
  "notifications": [
    {
      "userId": "abcde",
      "type": "type",
      "postId": "postId",
      "postImageUrl": "postImageUrl",
      "timeStamp": "timeStamp",
      "username": "username",
      "photoUrl": "photoUrl"
    }
  ]
}
One workaround to this is creating a dedicated
data class
to send the response:
Copy code
@Serializable
data class NotificationDtoResponse(
    val key: Long,
    val pageSize: Int,
    val notifications: List<NotificationDto>
)
Copy code
call.respond(
    NotificationDtoResponse(
        pageSize = 10,
        key = System.currentTimeMillis(),
        notifications = notificationsDtoList
    )
)
Not sure, it’s the correct way to do it
a
This is actually not a workaround but the recommended way to do it.
k
Okay, thanks a lot for helping 😇