JSON Converter Library
JSON이란?
JavaScript 객체 문법으로 구조화 된 데이터 교환 형식
{
"name": "홍길동",
"age": 20
}
직렬화 & 역직렬화
직렬화 : 외부의 시스템에서도 사용할 수 있도록 바이트 형태로 데이터를 변환하는 기술
역직렬화: 바이트 형태의 데이터를 객체로 변환하는 기술
서버에서 데이터를 받을 때 혹은 유저가 서버에 데이터를 보낼 때 주로 JSON형식으로 데이터를 변환하여 서로 주고 받는다.
사용자가 데이터를 전송할 때 해당 데이터를 JSON으로 변환하여 보내줄 필요가 있는데 이를 직렬화(Serialization)라고 하며,
반대로 JSON으로 넘어온 데이터를 그대로 사용하기 어려우니 JSON형식의 데이터를 나의 환경에 맞는 데이터 형식으로 바꿔주는 것을 역직렬화(DeSerialization)이라고 한다.
라이브러리 종류
1. Gson
- Java 기반 라이브러리
- 리플렉션 사용
- Kotlin의 null-safety를 고려하지 않음
- Default Value가 적용되지 않음
{
"name": "홍길동",
"age": 20,
"phone_number": "010-1234-5678"
}
data class User(
val name: String,
val age: Int,
val phoneNumber: String,
val address: String
)
Json 데이터를 User 객체로 변환 시 Json에 없는 address 값은 null로 넘어온다.
이때, address는 non-null 인데 값은 null이 들어가게 되는 문제가 생긴다.
data class User(
val name: String,
val age: Int,
val phoneNumber: String,
val address: String = "서울특별시"
)
이를 위해 address에 default value를 지정 후 변환해도 Gson은 default value 값이 적용되지 않는다.
따라서 Gson을 사용하는 경우 Nullable하게 선언해주어야 하며, Null Check를 해주어야 한다.
2. Kotlinx Serialization
- 리플렉션 미사용
- Default Value 적용
- null-safety
Gson에 대한 대안으로 Kotlinx-Serialization이 있다.
속성
import kotlinx.serialization.json.Json
fun serializationJson(){
Json {
ignoreUnknownKeys = true
coerceInputValues = true
encodeDefaults = true
explicitNulls = true
isLenient = true
}
}
[DeSerialization]
- ignoreUnknownKeys: 추가적인 Json 키가 존재하는 경우 이를 무시한다.
{
"name": "홍길동",
"age": 20,
"address": "서울"
}
@Serialization
data class User(
val name: String,
val age: Int
)
- coerceInputValues: 데이터 타입이 non-null이며, 해당 키의 값이 null이라면 Default Value 값 적용
(해당 속성이 false이며, non-null 타입에 null이 들어오면 에러 발생)
{
"name": "홍길동",
"age": 20,
"address": null
}
@Serialization
data class User(
val name: String,
val age: Int,
val address: String = "주소"
)
- isLenient: Json의 Key와 Value가 따옴표로 구성되지 않은 경우에도 파싱할 수 있다.
{
name: 홍길동,
age: 20,
address: 서울
}
@Serialization
data class User(
val name: String,
val age: Int,
val address: String
)
[Serialization]
- encodeDefaults: Json 변환 시 Defalut Value 적용
(해당 속성 false 시, Defalut Value 필드는 생략되어 변환된다.)
@Serialization
data class User(
val name: String,
val age: Int = 20,
val address: String = "주소"
)
fun main(){
val format = Json { encodeDefaults = true }
val user = User("홍길동")
val json = format.encodeToString(user)
println(json)
}
// 결과
{
"name": "홍길동",
"age": 20,
"address": "주소"
}
// encodeDefault = false 결과
{
"name": "홍길동"
}
- explicitNulls: null 필드는 Json으로 변환 시 생략한다.
@Serialization
data class User(
val name: String,
val age: Int,
val address: String?
)
fun main(){
val format = Json { explicitNulls = true }
val user = User("홍길동", 20, null)
val json = format.encodeToString(user)
println(json)
}
// 결과
{
"name": "홍길동",
"age": 20
}
이외의 다양한 Json 속성들은 https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md 참고
3. Moshi
- 리플렉션을 사용하지 않고 컴파일 타임에 클래스 필드 타입 정보를 확인하여 빠른 성능을 보여준다.
- Kotlin 높은 호환성
- Gson을 차용하여 개발되어 큰 문제없이 Gson에서 Moshi로 이전이 가능하다.
- Okio 기반으로 개발되어 강력한 I/O 처리를 제공해주어 성능에 큰 이점을 갖는다.
- Retrofit과 함께 사용했을 경우 메모리 버퍼를 재사용하여 메모리 할당 및 해제에 드는 오버헤드 감소 효과
(참고 자료: https://blog.imqa.io/json-moshi/ )
Moshi vs Kotlinx-Serialization에 대한 내용