Gson 라이브러리 사용하기
안녕하세요.
오늘은 안드로이드에서 json 데이터를 다룰때 사용하는 Gson에 대해서 설명하도록 하겠습니다.
gson 라이브러리는?
JSON 포멧의 데이터를 직렬화(Serialization), 역직렬화(Deserialization)할때 편리하게 사용할 수 있도록 google에서 개발한 JSON 데이터처리 라이브러리입니다.
우리는 주로 앱과 서버가 통신을 할때 JSON 혹은 XML을 데이터로 주고 받습니다.
이때 JSON 데이터를 받아서 모델 클래스에 주입할 수 있게 도와주는 역할을 합니다.
GSON 없이 JSON 데이터를 파싱하려면 생각보다 많은 코드가 필요합니다.
GSON을 이용하면 간편하게 몇 줄 안에 원하는 형태로 사용할 수 있게 도와줍니다.
Gradle기준 GSON을 사용하려면 다음과 같이 라이브러리를 추가해줍니다.
dependencies { implementation 'com.google.code.gson:gson:2.8.9' }
기준이 되는 JSON은 다음과 같습니다.
{
"drama_title": "좋좋소",
"drama_season": 4,
"company_list": [
{
"name": "JPD 소프트",
"member_list": [
{
"name": "정필돈",
"age": 50,
"career": {
"position": "사장",
"year": 20
}
},
{
"name": "이미나",
"age": 32,
"career": {
"position": "영업",
"year": 4
}
},
{
"name": "이예영",
"age": 24,
"career": {
"position": "개발",
"year": 1
}
}
]
},
{
"name": "백인터내셔날",
"member_list": [
{
"name": "백진상",
"age": 48,
"career": {
"position": "사장",
"year": 18
}
},
{
"name": "이과장",
"age": 47,
"career": {
"position": "영업",
"year": 15
}
},
{
"name": "조충범",
"age": 33,
"career": {
"position": "영업",
"year": 2
}
}
]
}
]
}
위의 JSON을 역직렬화 시켜줄 data class를 정의합니다.
최상위의 데이터를 DramaModel로 지정하고 다음과 같이 data class를 구성하였습니다.
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
data class DramaModel(
@SerializedName(value = "drama_title") @Expose val dramaTitle: String,
@SerializedName(value = "drama_season") @Expose val dramaSeason: String,
@SerializedName(value = "company_list") @Expose val companyList: ArrayList<CompanyListModel>
)
JSON파일의 company_list는 ArrayList로 자료형을 지정했습니다. JSON의 배열 형태의 데이터는 ArrayList로 받을 수 있습니다.
CompanyListModel은 다음과 같이 구성하였습니다.
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
data class CompanyListModel(
@SerializedName(value = "name") @Expose val name: String,
@SerializedName(value = "member_list") @Expose val memberList: ArrayList<MemberModel>
)
MemberModel은 다음과 같이 구성하였습니다. MemberModel의 career는 key : value쌍의 HashMap 형태로 지정합니다. HashMap이 아니어도 하위의 data class의 형태로 지정하면 데이터를 받을 수 있습니다.
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
data class MemberModel(
@SerializedName(value = "name") @Expose val name: String,
@SerializedName(value = "age") @Expose val age: Int,
@SerializedName(value = "career") @Expose val careerMap: Map<String, String>
)
데이터를 이렇게 지정했으면 다음과 같은 방법으로 사용합니다.
이해하기 쉽기 위해서 우선 서버와 같이 어디선가 JSON 데이터를 받을 수 있다고 가정하고, 역직렬화부터 진행하도록 하겠습니다.
역직렬화 (Deserialize) - (String -> Object)
String형태의 JSON 데이터를 DummyJsonData.getJsonData: String 메서드로 받아서 DramaModel 클래스에 주입해주는 코드입니다. Gson().fromJson(String, Model::class.java)의 형태로 사용합니다.
예시 코드는 아래와 같습니다.
private fun deserializeJsonData(): DramaModel? {
return Gson().fromJson(DummyJsonData.getJsonData(), DramaModel::class.java).also { model ->
Log.d(TAG, "deserializeJsonData: $model")
}
}
직렬화 (Serialize) - (Object -> String)
Object 형태를 JSON String 형태로 변환해주는 코드입니다. Gson().toJson의 형태로 사용합니다.
private fun serializeJsonData(): String {
var jsonString: String = ""
deserializeJsonData().also { model ->
jsonString = Gson().toJson(model)
Log.d(TAG, "serializeJsonData: $jsonString")
}
return jsonString
}
직렬화를 수행해서 내용물을 출력해보면 다음과 같이 보기 힘든 형태로 나타납니다.
{"company_list":[{"member_list":[{"age":50,"career":{"position":"사장","year":"20"},"name":"정필돈"},{"age":32,"career":{"position":"영업","year":"4"},"name":"이미나"},{"age":24,"career":{"position":"개발","year":"1"},"name":"이예영"}],"name":"JPD 소프트"},{"member_list":[{"age":48,"career":{"position":"사장","year":"18"},"name":"백진상"},{"age":47,"career":{"position":"영업","year":"15"},"name":"이과장"},{"age":33,"career":{"position":"영업","year":"2"},"name":"조충범"}],"name":"백인터내셔날"}],"drama_season":"4","drama_title":"좋좋소"}
이것을 보기 편한 형태로 변환해주는 방법이 있습니다. GsonBuilder()을 이용하는 방법인데요. 다음과 같이 사용합니다.
private fun setPrettyJsonData(): String {
var jsonString: String = ""
deserializeJsonData().let { model ->
jsonString = GsonBuilder().setPrettyPrinting().create().toJson(model)
Log.d(TAG, "setPrettyJsonData: $jsonString")
}
return jsonString
}
샘플코드는 아래 github에서 확인할 수 있습니다.
참고한 사이트는 다음과 같습니다.