Kotlin에서 reflection을 사용하여 JSON serialization 해보기에 이어서, deserialization을 구현해본다.
KClass
type을 사용해 변환할 class type을 받는다.fun <TR: Any> deserializeMap(type: KClass<TR>, map: Map<String, Any>): TR
KClass.primaryConstructor
로 기본 생성자 정보를 가져올 수 있다. 생성자의 parameter 정보들을 KParameter
type으로 가져와 parameterInfo
에 저장할 것이다val parameterInfo = mutableMapOf<KParameter, Any?>()
type.primaryConstructor?.parameters?.forEach {
...
}
KClass.primaryConstructor.name
으로 생성자 parameter의 이름, 즉 member value를 가져올 수 있다. JSON Map에서 member value를 key로 가진 item을 찾는다val item = map[it.name]
if(item is JSONObject) {
// Performing recursive transformations
} else if(item is JSONArray) {
// Deserialize each item in an array and store it in a List
} else if(item != null) {
// Ignore
} else {
// Ignore
}
parameterInfo
에 KParamter
와 deserialize한 value 값을 저장한다.if(item is JSONObject) {
// Performing recursive transformations
parameterInfo[it] = deserializeMap(it.type.classifier as KClass<*>, jsonObjectToMap(item))
}
} else if(item is JSONArray) {
val list = mutableListOf<Any?>()
val template = it.type.arguments[0].type!!.classifier
for(subItem in jsonListToList(item)) {
if(subItem is JSONObject) {
list.add(deserializeMap(template as KClass<*>, jsonObjectToMap(subItem)))
}
}
parameterInfo[it] = list
}
} else if(item != null) {
parameterInfo[it] = item
} else {
parameterInfo[it] = null
}
List<KParameter, Any?>
값을 생성자의 parameter로 넘겨 실행하면 deserialize된 instance를 얻을 수 있다.return type.primaryConstructor?.callBy(parameterInfo)!!
fun deserialize(): Any {
val jsonString = """
{
"age": 30,
"height": 171.2,
"name": "John Doe",
"subWorkplace": [
{
"isLargeEnterprise": true,
"name": "Google"
}
],
"workplace": {
"isLargeEnterprise": true,
"name": "Google"
}
}
""".trimIndent()
val result = JJson().deserializeMap(Person::class, JJson.jsonStringToMap(jsonString))
Log.d(TAG, "Deserialize result: $result")
return result
}
Deserialize result: Person(name=John Doe, age=30, height=171.2, workplace=Company(name=Google, isLargeEnterprise=true, numOfEmployees=null), subWorkplace=[Company(name=Google, isLargeEnterprise=true, numOfEmployees=null)])