(Android/안드로이드) Gson 실무 활용법 - 모델 파싱, 제네릭, 버전관리 등

개요


1. Gson을 “파서”로만 쓰지 말고 “경계(Boundary)”로 쓰기


2. 기본 사용: 객체 ↔ JSON

data class People(val id: Int, val name: String)

// 매번 생성하는 방식
val gson = Gson()
val json = gson.toJson(People(1, "kim"))
val obj = gson.fromJson(json, People::class.java)

// 싱글톤으로 재사용
object GsonProvider {
    val gson: Gson = GsonBuilder()
        .serializeNulls() // 필요할 때만
        .create()
}

3. 제네릭 파싱 (TypeToken) — 실무에서 가장 자주 씀

3-1. List/Map

val type = object : TypeToken<List<People>>() {}.type
val list: List<People> = GsonProvider.gson.fromJson(json, type)

3-2. 공통 응답 Wrapper

// json : { "code": 0, "data": { "id": 1, "name": "kim" } }

data class ApiResponse<T>(
    val code: Int,
    val data: T?
)

val type = object : TypeToken<ApiResponse<People>>() {}.type
val res: ApiResponse<People> = GsonProvider.gson.fromJson(json, type)

4. 파싱 실패 방어: “크래시 대신 null/에러 객체”

inline fun <reified T> Gson.safeFromJson(json: String): T? =
    runCatching {
        fromJson(json, object : TypeToken<T>() {}.type)
    }.getOrNull()

val people: People? = GsonProvider.gson.safeFromJson(json)

5. 서버 필드 변경 대응: default 값 / Nullable 설계

data class PeopleDto(
    val id: Int? = null,
    val name: String? = null
)

data class People(
    val id: Int,
    val name: String
)

fun PeopleDto.toDomain(): People? {
    val safeId = id ?: return null
    val safeName = name ?: return null
    return People(safeId, safeName)
}

6. 날짜/시간 파싱: 커스텀 포맷 고정

val gson = GsonBuilder()
    .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    .create()


Related Posts