API로 받은 필드 값이 고정 타입이 아니라면 어떻게 받아야 할까?
"type": "event",
"info": {
"eventId": 613,
"eventUrl": "https://string.com",
"eventName": "ttttt",
"eventType": "offline"
}
"type": "post",
"info": {
"postId": 12,
"commentId": 1080,
"postUserId": 2,
"commentUserId": 781
}
서버에서 "info" 필드는 타입에 따라 다른 필드들을 받는다.
이런 경우 클라이언트에서는 info를 Map<String, Any> 형태로 받아서 처리하는 방법이다.
@SerializedName("type")
@Expose val type: String
@SerializedName("info")
@Expose val info: Map<String, Any>
클라이언트에서 사용할 모델 구조
data class Notification(
val type: Type,
val info: Info,
)
sealed class Info {
data class EventInfo(
val eventId: Long,
val eventUrl: String,
val eventName: String,
val eventType: String
) : Info()
data class ProductInfo(
val postId: Long,
val commentId: Long,
val postUserId: Long,
val commentUserId: Long
) : Info()
}
Mapping ( GetNotification -> Notification )
NotificationData(
type = type,
info = mapToData(type, notification.info),
)
private fun mapToData(
type: NotificationData.Type,
content: Map<String, Any>
): NotificationData.Info {
return when (type) {
NotificationData.Type.EVENT -> {
NotificationData.Info.EventInfo(
eventId = (content?.get("eventId") as? Double)?.toLong() ?: 0L,
eventUrl = (content?.get("eventUrl") as? String) ?: "",
eventName = (content?.get("eventName") as? String) ?: "",
eventType = (content?.get("eventType") as? String) ?: "",
)
}
NotificationData.Type.POST -> {
NotificationData.Info.PostInfo(
postId = (content?.get("postId") as? Double)?.toLong() ?: 0L,
commentId = (content?.get("commentId") as? Double)?.toLong() ?: 0L,
postUserId = (content?.get("postUserId") as? Double)?.toLong() ?: 0L,
commentUserId = (content?.get("commentUserId") as? Double)?.toLong() ?: 0L,
)
}
}
각각의 타입에 맞게 직접 필드명으로 꺼내와서 타입캐스팅 하여 맵핑.
(*주의할점은 서버에서 Int 값을 Retrofit 으로 가져올때 타입이 Double 타입이라는 것)
추가로 응용버전으로 중첩 구조가 한단계 더 있는 경우에 대한 예제
data class UsageQuestion(
val answer: Answer
) : Question() {
data class Answer(
val correct: List<Correct>
) {
data class Correct(
val text: String,
val wrong: String
)
}
}
한뎁스에서 꺼내오고, 그 안의 뎁스에서 꺼내오기.
val answer = (question["answer"] as? Map<String, Any>)
val correct = (answer?.get("correct") as? List<Map<String, Any>>)
answer = EntryData.Question.UsageQuestion.Answer(
correct = correct?.map { correct ->
EntryData.Question.UsageQuestion.Answer.Correct(
text = (correct["text"] as? String) ?: "",
wrong = (correct["wrong"] as? String) ?: ""
)
} ?: emptyList()
)
'Android' 카테고리의 다른 글
DiffUtil 사용시 정렬후 스크롤 Top 으로 이동하기 (0) | 2021.12.29 |
---|---|
시간 간격 계산하여 x분전, x시간 전으로 변형하기 (0) | 2021.12.24 |
리사이클러뷰 중첩 구조를 하나의 리사이클러뷰로 리팩토링 과정 (0) | 2021.09.29 |
카카오 로그인 Trouble Shooting (0) | 2021.09.29 |
어댑터 초기화후 데이터 넣기 (0) | 2021.09.10 |