'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