프로젝트 리소스에 포함된 Json 파일을 불러와 List로 만들 일이 생겼다.
이 과정을 위해 해준 일들을 우선 나열해보면 4단계 정도가 있다.
1. 프로젝트에 Assets 폴더를 만들고 불러오고자 하는 json 파일을 집어넣는다.
2. GSON 라이브러리 및 Room Database import
3. Json 파일로부터 만들고자 하는 Data class를 정의
(3-1) 필요한 경우에 따라 TypeConverter 추가 정의
4. Json 파일을 String 객체로 Parsing > Gson 사용해 List 뽑아내기
Json Parsing을 위해 Gson과 AAC의 Room을 사용했다.
그러면 1번부터 쭉 밟아보자.
1. 프로젝트에 Assets 폴더를 만들고 불러오고자 하는 json 파일을 집어넣는다.
2. GSON 라이브러리 및 Room Database import
아래 항목들을 app수준 gradle의 dependency 내에 추가한다.
- GSON
implementation 'com.google.code.gson:gson:2.8.6'
- Room
// Room
def room_version = "2.2.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
여기서 Room 셋업을 하면서 조금 애를 먹었는데, 이를 해결하기 위해 상단의 android / defaultConfig 내에 하단 코드를 추가했다.
android {
...
defaultConfig {
...
// Room 설정을 위해 추가한 부분
javaCompileOptions {
annotationProcessorOptions {
arguments = [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
}
}
...
}
3. Json 파일로부터 만들고자 하는 Data class를 정의
@Entity(tableName= "sample")
data class SampleData(
@PrimaryKey(autoGenerate = false)
@ColumnInfo(name = "name")
var name: String,
@ColumnInfo(name = "location")
var location: String,
@ColumnInfo(name = "initial")
@TypeConverters(SampleTypeConverter::class)
@SerializedName("reservations")
var reservations: List<Reservations>?,
@ColumnInfo(name = "is_full")
var is_full: Int
)
Json파일로부터 Parsing해 받아올 데이터를 Room 데이터 클래스로 정의한다.
이때 컬럼들은 Json이 담고있는 형식 및 이름을 같게 해준다.
혹 json의 특정 부분이 배열을 포함하고 있는 경우에는 상단 코드와 같이 List<배열의내용을담은클래스> 를 선언하고,
이를 TypeConvert를 달아 처리를 해주어야만 문제없이 Parsing이 가능해진다.
(3-1) 필요한 경우에 따라 TypeConverter 추가 정의
class SampleTypeConverter {
companion object {
@TypeConverter
@JvmStatic
fun fromString(value: String?): List<Reservations?>? {
val listType: Type =
object : TypeToken<List<Reservations?>?>() {}.type
return Gson().fromJson(value, listType)
}
@TypeConverter
@JvmStatic
fun listToString(list: List<Reservations?>?): String? {
val gson = Gson()
return gson.toJson(list)
}
}
}
TypeConverter는 리스트 형식의 데이터를 Room에 저장하고, 또 불러올 수 있게 해주는 클래스로 리스트가 포함된 경우 참조해
필수적으로 구현하자.
4. Json 파일을 String 객체로 Parsing > Gson 사용해 List 뽑아내기
private fun parseJson(): List<SampleData> {
val gson = Gson()
val testString: String
// 파일 입력에 오류가 있을 경우의 예외처리
try {
testString = applicationContext.assets.open("FILE.json")
.bufferedReader()
.use {it.readText()}
} catch (e: FileNotFoundException) {
e.printStackTrace()
return emptyList()
}
return gson.fromJson(testString, Array<SampleData>::class.java).toList()
}
이제 데이터 정의가 다 끝났으면 function을 적당히 정의해 집어넣어둔 Json 파일을 가져오자.
gson 객체를 정의하고, testString에 1차적으로 Json파일을 String화 > 이를 gson.fromJson()메소드를 사용해 List형태로 뽑아낼 수 있게 된다.