如何在 Kotlin 中将地图和嵌套地图转换为字符串,反之亦然?

How to convert map and nested map to string and vise versa in Kotlin?

我不知道如何将 HashMap 和嵌套 Hashmap 转换为字符串,反之亦然:

我使用 Room 将数据保存在本地数据库中。 "users" hashmap 是数据 class 的一个参数。要在Room数据库中保存这个参数"users",我们必须将其转换为原始类型,如string、boolen、Integer等。Room不支持对象引用,所以type converters 是必需的。

val users = HashMap<String, HashMap<String, Any>>()

    val user1 = HashMap<String, Any>()
    user1["filter"] = 0
    user1["group"] = "groupId"
    user1["labelsVisibility"] = true
    user1["sort"] = 1
    user1["view"] = 3
    users["user1"] = user1

    val user2 = HashMap<String, Any>()
    user2["filter"] = 0
    user2["group"] = "groupId"
    user2["labelsVisibility"] = true
    user2["sort"] = 1
    user2["view"] = 3
    users["user2"] = user2

解决方案

可能有更好的方法来做到这一点,但它有效

  1. 使用特殊符号将 HashMap<String, HashMap<String, Any>> 转换为字符串 * + (符号在字符串中必须是唯一的)

     fun fromUsersPreferences(users: HashMap<String, HashMap<String, Any>>): String {
       var usersString = ""
       users.forEach {
         usersString = usersString.plus("${it.key}*${it.value}+")
       }
       usersString = usersString.dropLast(1)
       return usersString
     }
    

输出:

"user1*{filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}+user2*{filter=1, view=1, labelsVisibility=false, sort=0, group=groupId}"
  1. 将字符串转换为 HashMap<String, HashMap<String, Any>>

    fun toUsersPreferences(users: String): HashMap<String, HashMap<String, Any>> {
     val usersMap = users.split("+").associateTo(HashMap()){
         val list = it.split("*")
         val userKey = list[0]
         val userValue = list[1].removeSurrounding("{", "}").split(", ").associateTo(HashMap()){
             val (key, value) = it.split("=")
             if (key.equals("group")) {
                 Pair<String, Any>(key, value)
             } else if (key.equals("labelsVisibility")) {
                 Pair<String, Any>(key, value.toBoolean())
             } else {
                 Pair<String, Any>(key, value.toInt())
             }
         }
    
         Pair(userKey, userValue)
     }
    
     return usersMap
    }
    

输出:

{user1={filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}, user2={filter=1, view=1, labelsVisibility=false, sort=0, group=groupId}}

正如我之前在评论中所说,可以使用 Gson 库轻松完成:

// Configure Gson
val gson = GsonBuilder()
    // Using this strategy Gson first tries converting number to Long. 
    // If it fails (number is float), then it tries converting to Double
    .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) 
    .create()

// Convert to JSON string
val jsonString = gson.toJson(users)
println("JSON => $jsonString")

// Store at Room as a string...
// Fetch later from Room as a string...

val type = object : TypeToken<HashMap<String, HashMap<String, Any>>>() {}.type
val fromJsonMap: HashMap<String, HashMap<String, Any>> = gson.fromJson(jsonString, type)

println("ORIGINAL MAP =>\n$users")
println("RESTORED MAP =>\n$fromJsonMap")

输出:

JSON => {
  "user1": {
    "filter": 0,
    "view": 3,
    "labelsVisibility": true,
    "sort": 1,
    "group": "groupId"
  },
  "user2": {
    "filter": 0,
    "view": 3,
    "labelsVisibility": true,
    "sort": 1,
    "group": "groupId"
  }
}

ORIGINAL MAP =>
{user1={filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}, user2={filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}}
RESTORED MAP =>
{user1={filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}, user2={filter=0, view=3, labelsVisibility=true, sort=1, group=groupId}}

如您所见,原始地图 users 和恢复后的地图 fromJsonMap 完全相同。