You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Kotlin数据类转换为Map并添加新键值对?

解决Kotlin数据类转Map并添加新键值对的问题

首先,你的核心需求是把嵌套的Kotlin数据类转换成可修改的Map,同时给每个DeviceGroup对应的Map添加devices键并填充数据。我们一步步来解决:

一、先解决数据类转Map的问题

Kotlin数据类没有内置的toMap()方法能处理嵌套结构(比如你的User里包含DeviceGroup集合,DeviceGroup又包含DeviceLink集合),所以我们有两种方案:

方案1:自己实现递归转换的扩展函数

这个方案适合不想引入第三方库的场景,我们写一个通用的扩展函数,递归处理所有嵌套的数据类和集合:

// 递归将任意数据类(及嵌套结构)转换为可修改的MutableMap
fun Any.toMutableMap(): MutableMap<String, Any?> {
    val resultMap = mutableMapOf<String, Any?>()
    
    // 只处理数据类
    if (this::class.isData) {
        this::class.memberProperties.forEach { property ->
            val value = property.get(this)
            resultMap[property.name] = when (value) {
                // 处理集合:把List/Set里的每个元素递归转Map,再转成可变集合
                is Collection<*> -> value.map { item -> item?.toMutableMap() }.toMutableList()
                // 处理Map:键转成String,值递归转Map
                is Map<*, *> -> value.mapKeys { it.key.toString() }
                    .mapValues { entry -> entry.value?.toMutableMap() }
                    .toMutableMap()
                // 基本类型/非数据类直接存入
                else -> value
            }
        }
    } else {
        // 非数据类(比如基本类型)的兜底处理
        resultMap["value"] = this
    }
    
    return resultMap
}

方案2:用Jackson库自动转换

如果你项目里已经用了Jackson(很多Spring项目都会用),直接用它的转换功能更省心,不用自己写递归逻辑:

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

// 初始化Jackson的Kotlin模块
val mapper = jacksonObjectMapper()

// 把User对象直接转成MutableMap
val response = mapper.convertValue(data, MutableMap::class.java) as MutableMap<String, Any?>

二、修改Map并添加新键值对

不管用哪种方案,我们得到的都是MutableMap(必须是可变的才能添加新键值对),接下来处理deviceGroup部分:

完整修正后的代码

fun main(request: HttpServletRequest) {
    val currentUser = request.session.getAttribute("user") as User
    val data = userRepository.findByName(currentUser.name)
    
    // 方案1:用自己写的扩展函数转成MutableMap
    val response = data.toMutableMap()
    
    // 方案2:用Jackson转(如果用这个就注释掉上面的方案1代码)
    // val mapper = jacksonObjectMapper()
    // val response = mapper.convertValue(data, MutableMap::class.java) as MutableMap<String, Any?>
    
    // 获取转换后的deviceGroup列表(注意类型是MutableList<MutableMap<String, Any?>>)
    val deviceGroups = response["deviceGroup"] as MutableList<MutableMap<String, Any?>>
    
    // 遍历每个deviceGroup的Map,添加devices键并填充数据
    deviceGroups.forEach { deviceGroupMap ->
        // 从当前deviceGroup的Map里拿到名称
        val groupName = deviceGroupMap["name"] as String
        // 从仓库获取完整的DeviceGroup(包含deviceLink数据)
        val fullDeviceGroup = deviceGroupRepository.findByName(groupName)
        
        // 把deviceLink里的Device转成Map,收集到Set中
        val devicesSet = fullDeviceGroup.deviceLink.map { deviceLink ->
            deviceLink.device.toMutableMap() // 用同样的扩展函数转Device为Map
        }.toMutableSet()
        
        // 给当前deviceGroup的Map添加新的键值对
        deviceGroupMap["devices"] = devicesSet
    }
    
    return response
}

// 如果你用方案1,需要把这个扩展函数加上
fun Any.toMutableMap(): MutableMap<String, Any?> {
    val resultMap = mutableMapOf<String, Any?>()
    
    if (this::class.isData) {
        this::class.memberProperties.forEach { property ->
            val value = property.get(this)
            resultMap[property.name] = when (value) {
                is Collection<*> -> value.map { item -> item?.toMutableMap() }.toMutableList()
                is Map<*, *> -> value.mapKeys { it.key.toString() }
                    .mapValues { entry -> entry.value?.toMutableMap() }
                    .toMutableMap()
                else -> value
            }
        }
    } else {
        resultMap["value"] = this
    }
    
    return resultMap
}

修正了你代码里的几个错误

  1. 拼写错误:deivceGroup改成了deviceGroup
  2. Map没有add方法:用deviceGroupMap["devices"] = devicesSet来添加新键值对
  3. 填充数据时的this错误:应该取deviceLink.device来转成Map

三、最终效果

转换后的response结构会是这样:

{
  "name": "test",
  "age": 17,
  "deviceGroup": [
    {
      "name": "group1",
      "devices": [{"devId": xxx, "name": xxx}, ...]
    },
    {
      "name": "group2",
      "devices": [{"devId": xxx, "name": xxx}, ...]
    }
  ]
}

内容的提问来源于stack exchange,提问作者Funniest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:57:54