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

WebFlux GET请求反序列化嵌套Map<String,Map<String,String>>报错如何解决

问题原因

报错的本质是Jackson反序列化时无法正确识别嵌套泛型的类型约束,错误将内层Map的值反序列化为LinkedHashMap对象,后续尝试强转为String时触发类型转换异常,大多数情况下是Kotlin环境下ParameterizedTypeReference匿名类的泛型信息丢失导致的。

解决方案

方案1:使用Kotlin reified泛型扩展(优先推荐,无需自定义序列化)

Spring WebFlux对Kotlin提供了带reified泛型的bodyToMono扩展方法,可以自动保留完整的嵌套泛型类型信息,避免手动声明ParameterizedTypeReference导致的类型擦除问题:

suspend fun getProperties(): Map<String, Map<String, String>> {
    return webClient
        .get()
        .uri("/property/all")
        .retrieve()
        // 直接使用带泛型的扩展方法,无需手动创建ParameterizedTypeReference
        .bodyToMono<Map<String, Map<String, String>>>()
        .awaitSingle()
}

需确保项目已引入以下依赖:

  • org.springframework.boot:spring-boot-starter-webflux(Spring Boot项目默认包含)
  • com.fasterxml.jackson.module:jackson-module-kotlin:Jackson对Kotlin的适配模块,可解决大部分Kotlin泛型反序列化问题

方案2:自定义嵌套Map反序列化器

如果方案1仍无法解决问题,可以自定义反序列化器强制指定嵌套结构的类型解析逻辑:

步骤1:编写自定义反序列化器

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.node.ObjectNode

class NestedStringMapDeserializer : JsonDeserializer<Map<String, Map<String, String>>>() {
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Map<String, Map<String, String>> {
        val rootNode = p.codec.readTree<JsonNode>(p) as ObjectNode
        val result = mutableMapOf<String, Map<String, String>>()
        // 遍历外层Map键值对
        rootNode.fields().forEach { (outerKey, innerNode) ->
            val innerMap = mutableMapOf<String, String>()
            // 遍历内层节点,强制将所有值转换为String类型
            innerNode.fields().forEach { (innerKey, valueNode) ->
                innerMap[innerKey] = valueNode.asText()
            }
            result[outerKey] = innerMap
        }
        return result
    }
}

步骤2:注册反序列化器到WebClient

import com.fasterxml.jackson.databind.module.SimpleModule
import org.springframework.http.codec.json.Jackson2JsonDecoder
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule

// 构造自定义ObjectMapper并注册反序列化器
val customObjectMapper = jacksonObjectMapper()
    .registerModule(KotlinModule.Builder().build())
    .registerModule(SimpleModule().apply {
        addDeserializer(object : com.fasterxml.jackson.core.type.TypeReference<Map<String, Map<String, String>>>() {}, 
            NestedStringMapDeserializer()
        )
    })

// 用自定义ObjectMapper构造WebClient实例
val webClient = WebClient.builder()
    .baseUrl("你的服务基础地址")
    .codecs { configurer ->
        configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(customObjectMapper))
    }
    .build()

如果是Spring Boot项目,也可以将包含自定义反序列化器的SimpleModule注册为Spring Bean,全局自动生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:30:04