'How to map a JSON string to Kotlin Map
I have a simple Kotlin program that access a Mongo database and produce a JSON string as below;
"{
"_id" : { "$oid" : "593440eb7fa580d99d1abe85"} ,
"name" : "Firstname Secondname" ,
"reg_number" : "ATC/DCM/1016/230" ,
"oral" : 11 ,
"oral_percent" : 73 ,
"cat_1" : 57 ,
"cat_2" : 60 ,
"cat_average" : 59 ,
"assignment" : 90
}"
How do I map this in Kotlin Map/MutableMap? Is there an API in Kotlin to read JSON and map it to Map/MutableMap?
Solution 1:[1]
This can be done with Klaxon. With this you can easily read the Json data as JsonObject
which is actually a MutableMap
.
val json: JsonObject = Parser().parse(jsonData) as JsonObject
Solution 2:[2]
No additional library is needed:
val jsonObj = JSONObject(jsonString)
val map = jsonObj.toMap()
where toMap is:
fun JSONObject.toMap(): Map<String, *> = keys().asSequence().associateWith {
when (val value = this[it])
{
is JSONArray ->
{
val map = (0 until value.length()).associate { Pair(it.toString(), value[it]) }
JSONObject(map).toMap().values.toList()
}
is JSONObject -> value.toMap()
JSONObject.NULL -> null
else -> value
}
}
Solution 3:[3]
Using Jackson's kotlin module, you can create a Map/MutableMap as below:
val jsonString = "{\n" +
" \"_id\": {\n" +
" \"\$oid\": \"593440eb7fa580d99d1abe85\"\n" +
" },\n" +
" \"name\": \"Firstname Secondname\",\n" +
" \"reg_number\": \"ATC/DCM/1016/230\",\n" +
" \"oral\": 11,\n" +
" \"oral_percent\": 73,\n" +
" \"cat_1\": 57,\n" +
" \"cat_2\": 60,\n" +
" \"cat_average\": 59,\n" +
" \"assignment\": 90\n" +
"}"
val map = ObjectMapper().readValue<MutableMap<Any, Any>>(jsonString)
Note: In case you're getting the below compilation error
None of the following functions can be called with the arguments supplied
Please ensure that you have added the the dependency of jackson-module-kotlin
(for gradle: compile "com.fasterxml.jackson.module:jackson-module-kotlin:${jackson_version}"
) and have added the import for the readValue implementation as import com.fasterxml.jackson.module.kotlin.readValue
in the place where you're using readValue
Solution 4:[4]
This can be done without any third party library:
@Throws(JSONException::class)
fun JSONObject.toMap(): Map<String, Any> {
val map = mutableMapOf<String, Any>()
val keysItr: Iterator<String> = this.keys()
while (keysItr.hasNext()) {
val key = keysItr.next()
var value: Any = this.get(key)
when (value) {
is JSONArray -> value = value.toList()
is JSONObject -> value = value.toMap()
}
map[key] = value
}
return map
}
@Throws(JSONException::class)
fun JSONArray.toList(): List<Any> {
val list = mutableListOf<Any>()
for (i in 0 until this.length()) {
var value: Any = this[i]
when (value) {
is JSONArray -> value = value.toList()
is JSONObject -> value = value.toMap()
}
list.add(value)
}
return list
}
Usage to convert JSONObject to Map:
val jsonObject = JSONObject(jsonObjStr)
val map = jsonObject.toMap()
Usage to convert JSONArray to List:
val jsonArray = JSONArray(jsonArrStr)
val list = jsonArray.toList()
More info is here
Solution 5:[5]
This is now also possible with kotlinx.serialization
:
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
val input = """{
"_id" : { "some_id" : "593440eb7fa580d99d1abe85"} ,
"name" : "Firstname Secondname" ,
"reg_number" : "ATC/DCM/1016/230" ,
"oral" : 11 ,
"oral_percent" : 73 ,
"cat_1" : 57 ,
"cat_2" : 60 ,
"cat_average" : 59 ,
"assignment" : 90
}"""
val json = Json.parseToJsonElement(input)
val map = json.jsonObject.toMap()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | tynn |
Solution 2 | Arutyun Enfendzhyan |
Solution 3 | |
Solution 4 | |
Solution 5 |