Kotlin:具有TypeReference <HashMap <String,String >>的objectmapper.readValue()无法推断参数

Dán*_*Kis 3 jackson kotlin

我想使用以下代码反序列化一个json以使用objectmapper映射:

fun onMessage(topic: String, message: MqttMessage) {
   val typeRef = object : TypeReference<HashMap<String, String>>() {}
   val msg = objectMapper.readValue(message.payload, typeRef)
   ...
}
Run Code Online (Sandbox Code Playgroud)

编译器表示不会推断参数T in fun <T : Any!> readValue (src: ByteArray!, valueTypeRef: (TypeReference<Any!>..TypeReference<*>?)): T!

如果用我的自定义类扩展HashMap,是否有解决此问题的方法:

class MyHashMap : HashMap<String, String>()
Run Code Online (Sandbox Code Playgroud)

...

fun onMessage(topic: String, message: MqttMessage) {
   val msg = objectMapper.readValue(message.payload, MyHashMap::class.java)
   ...
}
Run Code Online (Sandbox Code Playgroud)

zsm*_*b13 6

实际上,问题出在杰克逊的API中。这里是如何的readValue方法声明:

public <T> T readValue(String content, TypeReference valueTypeRef)
Run Code Online (Sandbox Code Playgroud)

他们TypeReference出于某种原因使用原始类型,即使可以轻松地将a TypeReference<T>作为其参数。如果这样做的话,您的代码将按原样工作,因为Kotlin然后可以推断T该函数的泛型类型参数,从而知道其返回类型。

但是,可以通过使用类型明确来解决此问题。

  • 通过为函数提供通用类型参数,并msg推断变量的类型:

    val msg = objectMapper.readValue<HashMap<String, String>>(message.payload, typeRef)
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者,通过显式键入变量并推断出函数的type参数,可以:

    val msg: HashMap<String, String> = objectMapper.readValue(message.payload, typeRef)
    
    Run Code Online (Sandbox Code Playgroud)

  • 你能展示一下你是如何声明“typeRef”的吗?我无法让你的例子发挥作用。尝试了这个 ```val typeRef: TypeReference&lt;List&lt;UserInfo&gt;&gt; = TypeReference&lt;List&lt;UserInfo&gt;&gt; (){}``` 但 IDE 告诉我“无法访问 &lt;init&gt;” (8认同)

rvi*_*t34 6

一种可能的方式:

inline fun <reified T> ObjectMapper.readValue(s: String): T = this.readValue(s, object : TypeReference<T>() {})

val msg: Map<String,String> = objectMapper.readValue(message.payload) 
Run Code Online (Sandbox Code Playgroud)