카테고리 없음

Enum SafeValueOf

그란. 2021. 3. 15. 17:51

(기존) 

[Remote Layer]

data class GetResponse(	
    @SerializedName("status")
    @Expose
    val status: StatusResponse
    ...
){
    enum class StatusResponse {
        @SerializedName("paid")
        @Expose
        PAID,

        @SerializedName("ready")
        @Expose
        READY;
    }
}
   

[Data Layer]

data class Data(
    val status: StatusData
    ...
){
    enum class StatusData {
        PAID,
        READY;
    }
}

[Mapping]

object StatusMapper :
        Mapper<GetResponse.StatusResponse, Data.StatusData> {
        override fun mapToData(from: GetResponse.StatusResponse): Data.StatusData {
            return when (from) {
                GetResponse.StatusResponse.PAID -> Data.StatusData.PAID
                GetResponse.StatusResponse.READY -> Data.StatusData.READY
             }
        }
 }

-> 각 레이어의 Enum끼리 맵핑 했었음 ( 1:1 ) 

 

 

-> 문제점 : 서버에서 paid, ready 외의 값이 추가되는 경우엔 매번 클라이언트에서도 맞춰줘야 맵핑이 됨 ( 그렇지 않으면 오류 발생 )

-> Enum safe valueOf 를 이용해야함


 

(수정) 

[Common] : 공용으로 사용하는 모듈

interface SafeEnumValue {
    val value: String
}

 

[Remote Layer]

data class GetResponse(	
    @SerializedName("status")
    @Expose
    val status: String
    ...
)
   

 

[Data Layer]

data class Data(
    val status: StatusData
    ...
){ 
   enum class StatusData : SafeEnumValue {
        PAID {
            override val value: String
                get() = "paid"
        },
        READY {
            override val value: String
                get() = "ready"
        },
        NONE {
            override val value: String
                get() = "none"
        };
    }
}

 

[Mapping]

inline fun <reified T> String.enumValueOrNull(): T? where T : Enum<*>, T : SafeEnumValue =
    T::class.java.enumConstants?.firstOrNull { it.value == this }


object StatusMapper :
    Mapper<String, Data.StatusData> {
    override fun mapToData(from: String): Data.StatusData {
        return from.enumValueOrNull() ?: Data.StatusData.NONE
    }
}

 

-> String 으로 받아서 비교후에 overriding 된 value의 Enum 리턴, 매칭되는 값이 없으면 기본값 NONE

 

 

-> 좀더 깔끔하게 하는 방법이 없을까?