https://yuar.tistory.com/entry/API-Response-Map-%ED%98%95%ED%83%9C%EB%A1%9C-%EB%B0%9B%EA%B8%B0
Map형태로 받아서 맵핑 하는 방법도 있는데
이번엔 바로 sealed class로의 맵핑을 해보려고 한다
서버에서 받아온 Data 예시1)
{
"context" : {
"name" : "count",
"param" : {
"count": Int
}
}
}
서버에서 받아온 Data 예시2)
{
"context" : {
"name" : "result",
"param" : {
"result": String
}
}
}
param은 두가지 종류로 올 수 있다.
data class Param(
val count : Int?,
val result :String?
)
이런 형태로 할수도 있겠지만 이러면 null 체크 계속 하게 되고 프로그래머가 계속 인지 하고 있어야 한다. ( 필드가 다수라면. )
하나의 형태로 묶어서 인스턴스 체크하는게 편리하기에. 아래와 같은 형태로 맵핑한다.
data class Context(
val name: String,
val param: Param
) {
sealed class Param {
data class A(
val count: Int
) : Param()
data class B(
val result: String
) : Param()
}
}
최종적으로는 이렇게 Context 클래스로 맵핑한다.
val response = gson.fromJson(model, Context::class.java)
하지만 이렇게 돌리면 에러가 발생한다 abstract class Param 은 파싱이 안된다고.
( sealed class 가 내부적으론 abstract class 로 되어있나보다 )
직접 역직렬화 해줘야한다
Gson을 생성한다.
"Param 클래스를 찾으면 직접 정의한 ParamTypeAdapter으로 역직렬화한다."
GsonBuilder()
.registerTypeAdapter(Param::class.java, ParamTypeAdapter)
.create()
object ParamAdapter : JsonDeserializer<Context.Params?> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): Context.Params? {
if (json == null || context == null) return null
val params = kotlin.runCatching {
json.asJsonObject
}.getOrNull() ?: return null
return when {
params.has("count") -> context.deserialize(
params,
Context.Params.A::class.java
)
params.has("result") -> context.deserialize(
params,
Context.Params.B::class.java
)
else -> null
}
}
}
일단 요기에서 json은 Param 객체를 지칭한다 ( 위에서 Param 객체를 만나면 이 클래스를 타라고 정의 했으니 )
json을 jsonObject ( gson 객체 ) 로 변환하고
해당 객체가 count 를 가졌는지, result 를 가졌는지에 따라 따로 역직렬화 한다.
추가적으로 DI를 사용하고 Gson 의 용도가 다른 경우 ( A 서버에서 내려주는 데이터의 경우, B서버에서 내려주는 데이터의 경우 )
별도로 네이밍일 지정해줘야하는데 힐트,대거의 경우 annotation class 를 지정해준다
@Qualifier
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FIELD
)
@Retention(AnnotationRetention.RUNTIME)
annotation class AServerQualifier
@Qualifier
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.FIELD
)
@Retention(AnnotationRetention.RUNTIME)
annotation class BServerQualifier
Gson 생성시 어노테이션
@Singleton
@AServerQualifier
@Provides
fun provideGson(): Gson {
}
사용하는 곳(주입받는곳)에서 어노테이션
@AServerQualifier private val gson: Gson,
'Android' 카테고리의 다른 글
build.gradle에 정의한 manifestPlaceholders 값 주입 받기 (0) | 2022.11.05 |
---|---|
카카오톡 채팅화면 키보드 옵션창 구현 (0) | 2022.10.09 |
특정 뷰위에 BottomSheet 올리기 (0) | 2022.09.29 |
카카오톡 잠금화면 구현 (0) | 2022.09.29 |
소셜 로그인 모듈화 과정 ( 추상화 및 액티비티 의존성 제거 ) (1) | 2022.09.29 |