【问题标题】:How to map a JSON string to Kotlin Map如何将 JSON 字符串映射到 Kotlin Map
【发布时间】:2022-05-03 16:14:38
【问题描述】:

我有一个简单的 Kotlin 程序,它可以访问 Mongo 数据库并生成如下 JSON 字符串;

"{
     "_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
}"

如何在 Kotlin Map/MutableMap 中映射它? Kotlin 中是否有 API 可以读取 JSON 并将其映射到 Map/MutableMap?

【问题讨论】:

标签: json kotlin


【解决方案1】:

不需要额外的库:

val jsonObj = JSONObject(jsonString)
val map = jsonObj.toMap()

toMap 在哪里:

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
    }
}

【讨论】:

  • 这似乎更像 Kotlin'esque - 赞成。 'value.toMap()' 递归调用非常有趣。此外,那个when-是有条件的,以前从未见过。从一篇文章中学到很多东西,你应该为每一个赞成票至少获得两次赞成票。
  • 很棒的答案。我只会用 (0 until value.length()).map { value[it] } 替换 JSONArray 部分 - 优雅而简洁。
  • @RomanKotenko 我不能,因为 JSONObject 只需要地图,而不是列表。我必须递归地使用 .toMap,以便将 JSONObject.NULL 转换为 null
  • @muzzletov ahahaha 谢谢
【解决方案2】:

这可以通过Klaxon 完成。有了这个,您可以轻松地将 Json 数据读取为JsonObject,这实际上是MutableMap

val json: JsonObject = Parser().parse(jsonData) as JsonObject

【讨论】:

  • Parser() 已弃用。 lib 建议使用 Parser.default() 代替
【解决方案3】:

使用 Jackson 的kotlin module,您可以创建一个 Map/MutableMap,如下所示:

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)

注意:如果您遇到以下编译错误

None of the following functions can be called with the arguments supplied

请确保您已添加 jackson-module-kotlin 的依赖项(对于 gradle:compile "com.fasterxml.jackson.module:jackson-module-kotlin:${jackson_version}"),并已将 readValue 实现的导入添加为 import com.fasterxml.jackson.module.kotlin.readValue 在您的位置重新使用readValue

【讨论】:

  • 我收到“readValue”错误,提示“以下函数都不能使用提供的参数调用。”
  • @Raksha 有帮助吗?
  • ObjectMapper().readValue(jsonString, MutableMap::class.java)
【解决方案4】:

这可以在没有任何第三方库的情况下完成:

@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
}

JSONObject转Map的用法:

val jsonObject = JSONObject(jsonObjStr)
val map = jsonObject.toMap()

JSONArray转List的用法:

val jsonArray = JSONArray(jsonArrStr)
val list = jsonArray.toList()

更多信息是here

【讨论】:

    【解决方案5】:

    现在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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多