如何使用 Kotlin + Jackson 将 JSON 反序列化为 List<SomeType>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34716697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I deserialize JSON into a List<SomeType> with Kotlin + Hymanson
提问by Jasper Blues
What is the correct syntax to deserialize the following JSON:
反序列化以下 JSON 的正确语法是什么:
[ {
"id" : "1",
"name" : "Blues"
}, {
"id" : "0",
"name" : "Rock"
} ]
I tried:
我试过:
//Works OK
val dtos = mapper.readValue(json, List::class.java)
However I want:
但是我想要:
val dtos : List<GenreDTO> = mapper.readValue(json,
List<GenreDTO>::class.java)
The above syntax is not correct and gives: only classes are allowed on the left hand side of a class literal
上面的语法不正确,给出: only classes are allowed on the left hand side of a class literal
回答by Jayson Minard
NOTE:The answer from @IRus is also correct, it was being modified at the same time I wrote this to fill in more details.
注意:@IRus 的答案也是正确的,它在我写这篇文章的同时被修改以填写更多细节。
You should use the Hymanson + Kotlin moduleor you will have other problems deserializing into Kotlin objects when you do no have a default constructor.
您应该使用Hymanson + Kotlin 模块,否则当您没有默认构造函数时,反序列化为 Kotlin 对象时会遇到其他问题。
Your first sample of the code:
您的第一个代码示例:
val dtos = mapper.readValue(json, List::class.java)
Is returning an inferred type of List<*>since you did not specify more type information, and it is actually a List<Map<String,Any>>which is not really "working OK" but is not producing any errors. It is unsafe, not typed.
List<*>由于您没有指定更多类型信息,因此返回推断类型,并且它实际上是一个List<Map<String,Any>>不是真正“工作正常”但没有产生任何错误的类型。它是不安全的,不是输入的。
The second code should be:
第二个代码应该是:
import com.fasterxml.Hymanson.module.kotlin.HymansonObjectMapper
import com.fasterxml.Hymanson.module.kotlin.readValue
val mapper = HymansonObjectMapper()
// ...
val genres: List<GenreDTO> = mapper.readValue(json)
You do not need anything else on the right side of the assignment, the Kotlin module for Hymanson will reify the generics and create the TypeReferencefor Hymanson internally. Notice the readValueimport, you need that or .*for the com.fasterxml.Hymanson.module.kotlinpackage to have the extension functions that do all of the magic.
您在作业的右侧不需要任何其他内容,Hymanson 的 Kotlin 模块将具体化泛型并在TypeReference内部为 Hymanson创建。请注意readValue导入,您需要它或.*让com.fasterxml.Hymanson.module.kotlin包具有执行所有魔术的扩展功能。
A slightly different alternative that also works:
一个稍微不同的替代方案也有效:
val genres = mapper.readValue<List<GenreDTO>>(json)
There is no reason to NOT use the extension functions and the add-on module for Hymanson. It is small and solves other issues that would require you to jump through hoops to make a default constructor, or use a bunch of annotations. With the module, your class can be normal Kotlin (optional to be dataclass):
没有理由不使用 Hymanson 的扩展功能和附加模块。它很小并且解决了其他需要您跳过箍以创建默认构造函数或使用一堆注释的问题。有了这个模块,你的班级就可以是普通的 Kotlin(可选是data班级):
class GenreDTO(val id: Int, val name: String)
回答by miensol
The error you're getting is about following expression:
您收到的错误与以下表达式有关:
List<GenreDTO>::class.java
Because of how jvm treats generics there's no separate class for List<GenreDTO>thus compiler complains. Similarly in Java the following will not compile:
由于 jvm 处理泛型的方式,List<GenreDTO>因此编译器抱怨没有单独的类。类似地,在 Java 中以下将不会编译:
List<GenreDTO>.getClass()
Here's a sample that will deserialize the list properly:
这是一个可以正确反序列化列表的示例:
val value:List<GenreDTO> = mapper.readValue(json, object : TypeReference<List<GenreDTO>>() {})
As @JaysonMinard has pointed out you can use Hymanson-module-kotlinto simplify the invocation to:
正如@JaysonMinard 指出的那样,您可以使用Hymanson-module-kotlin将调用简化为:
val genres: List<GenreDTO> = mapper.readValue(json)
// or
val genres = mapper.readValue<List<GenreDTO>>(json)
This is possible because of reified type parameters. Consider looking at Extensionsto find out details.
这是可能的,因为reified type parameters. 考虑查看Extensions以了解详细信息。
回答by Ruslan
Following code works well for me:
以下代码对我来说效果很好:
import com.fasterxml.Hymanson.databind.ObjectMapper
import com.fasterxml.Hymanson.module.kotlin.readValue
import com.fasterxml.Hymanson.module.kotlin.registerKotlinModule
val json = """[ {
"id" : "1",
"name" : "Blues"
}, {
"id" : "0",
"name" : "Rock"
} ]"""
data class GenreDTO(val id: Int, val name: String)
val mapper = ObjectMapper().registerKotlinModule()
fun main(args: Array<String>) {
val obj: List<GenreDTO> = mapper.readValue(json)
obj.forEach {
println(it)
}
}
This work because of extension function defined inside Hymanson-kotlin-module (that used reifiedgenerics):
这项工作是因为 Hymanson-kotlin-module 中定义的扩展函数(使用具体泛型):
public inline fun <reified T: Any> ObjectMapper.readValue(content: String): T = readValue(content, object: TypeReference<T>() {})
Thanks @JaysonMinard for notify me about it.
感谢@JaysonMinard 通知我。
Output:
输出:
GenreDTO(id=1, name=Blues)
GenreDTO(id=0, name=Rock)

