Generics 使用jackson模块kotlin反序列化泛型类
我正在尝试使用jackson kotlin集成。大多数情况下,它工作得很好,但我在反序列化泛型类型方面遇到了麻烦。我试着调整这个问题的答案: 显然,kotlin的jackson插件无法处理此问题。是否有解决方法或其他方法 顺便说一句,stringify函数是我为ObjectMapper添加的一个简单扩展函数,它负责处理样板代码:Generics 使用jackson模块kotlin反序列化泛型类,generics,kotlin,jackson,Generics,Kotlin,Jackson,我正在尝试使用jackson kotlin集成。大多数情况下,它工作得很好,但我在反序列化泛型类型方面遇到了麻烦。我试着调整这个问题的答案: 显然,kotlin的jackson插件无法处理此问题。是否有解决方法或其他方法 顺便说一句,stringify函数是我为ObjectMapper添加的一个简单扩展函数,它负责处理样板代码: /** * Serializes [value] to a string. Pretty prints if [pretty] is set. */ fun <
/**
* Serializes [value] to a string. Pretty prints if [pretty] is set.
*/
fun <T> ObjectMapper.stringify(value: T, pretty: Boolean = false): String {
val bos = ByteArrayOutputStream()
val writer = OutputStreamWriter(bos, StandardCharsets.UTF_8)
if(pretty) {
writerWithDefaultPrettyPrinter().writeValue(writer,value)
} else {
writeValue(writer, value)
}
writer.flush()
bos.flush()
return bos.toByteArray().toString(StandardCharsets.UTF_8)
}
/**
*将[value]序列化为字符串。如果设置了[Pretty],则显示Pretty打印。
*/
stringify(值:T,pretty:Boolean=false):String{
val bos=ByteArrayOutputStream()
val writer=OutputStreamWriter(bos,StandardCharset.UTF_8)
如果(漂亮){
writerWithDefaultPrettyPrinter().writeValue(writer,值)
}否则{
writeValue(writer,value)
}
writer.flush()
bos.flush()
返回bos.toByteArray().toString(StandardCharsets.UTF_8)
}
更新@jayson minard回答中的代码。事实证明,我的代码的关键区别在于我在测试方法中定义了数据类。把它们移到顶层可以解决问题。在函数中加入一个数据类一开始就不是一个好主意。使用Jackson的
2.9.6
,然后使用Jackson的主分支2.9.8
,以及当前的Jackson Kotlin模块,我添加了这个测试用例,它通过了您的代码版本和更干净的代码惯用版本
请注意,我还将stringify
方法更新为更加惯用的方法,但这不会影响测试
您对readValue
的调用也比必要的调用复杂得多。更改:
val parsed = objectMapper.readValue<Outer<Inner>>(serialized, objectMapper.typeFactory.constructParametricType(Outer::class.java, Inner::class.java))
val parsed=objectMapper.readValue(序列化的objectMapper.typeFactory.ConstructParameterType(外部::class.java,内部::class.java))
简单地说:
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
val parsed=objectMapper.readValue(序列化)
这是完全通过测试:
class TestStackOverflow53499407 {
data class Inner(val meaningOfLife: Int)
data class Outer<T>(val inner: T)
fun <T> ObjectMapper.stringify(value: T, pretty: Boolean = false): String {
StringWriter().use { writer ->
if (pretty) {
writerWithDefaultPrettyPrinter().writeValue(writer, value)
} else {
writeValue(writer, value)
}
return writer.toString()
}
}
@Test
fun test53499407_cleanTest() {
val outer = Outer(Inner(42))
val objectMapper = jacksonObjectMapper()
val serialized = objectMapper.stringify(outer, true)
println(serialized)
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
assertEquals(42, parsed.inner.meaningOfLife)
}
@Test
fun test53499407_idiomatic_tweek() {
val outer = Outer(Inner(42))
val jsonFactory = JsonFactory()
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
jsonFactory.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
val objectMapper = ObjectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.propertyNamingStrategy = PropertyNamingStrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized = objectMapper.stringify(outer, true)
println(serialized)
// This line changed to be idiomatic
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
assertEquals(42, parsed.inner.meaningOfLife)
}
@Test
fun test53499407_as_written_in_stackoverflow() {
val outer = Outer(Inner(42))
val jsonFactory = JsonFactory()
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
jsonFactory.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
val objectMapper = ObjectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.propertyNamingStrategy = PropertyNamingStrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized = objectMapper.stringify(outer, true)
println(serialized)
// deserializing does not work using:
// https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
val parsed = objectMapper.readValue<Outer<Inner>>(serialized, objectMapper.typeFactory.constructParametricType(Outer::class.java, Inner::class.java))
assertEquals(42, parsed.inner.meaningOfLife)
}
}
类TestStackOverflow53499407{
数据类内部(val意味着飞行:Int)
数据类外部(val内部:T)
stringify(值:T,pretty:Boolean=false):String{
StringWriter()。请使用{writer->
如果(漂亮){
writerWithDefaultPrettyPrinter().writeValue(writer,值)
}否则{
writeValue(writer,value)
}
return writer.toString()
}
}
@试验
趣味测试53499407_cleanTest(){
val外部=外部(内部(42))
val objectMapper=jacksonObjectMapper()
val serialized=objectMapper.stringify(外部,true)
println(序列化)
val parsed=objectMapper.readValue(序列化)
assertEquals(42,已解析。内部。表示飞行)
}
@试验
趣味测试53499407_惯用_tweek(){
val外部=外部(内部(42))
val jsonFactory=jsonFactory()
配置(JsonGenerator.Feature.AUTO\u CLOSE\u目标,false)
configure(JsonParser.Feature.IGNORE_未定义,true)
val objectMapper=objectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.PropertyNamegstrategy=PropertyNamegstrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized=objectMapper.stringify(外部,true)
println(序列化)
//这句话变成了惯用语
val parsed=objectMapper.readValue(序列化)
assertEquals(42,已解析。内部。表示飞行)
}
@试验
有趣的测试53499407_如_stackoverflow()中所述{
val外部=外部(内部(42))
val jsonFactory=jsonFactory()
配置(JsonGenerator.Feature.AUTO\u CLOSE\u目标,false)
configure(JsonParser.Feature.IGNORE_未定义,true)
val objectMapper=objectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.PropertyNamegstrategy=PropertyNamegstrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized=objectMapper.stringify(外部,true)
println(序列化)
//使用以下命令反序列化不起作用:
// https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
val parsed=objectMapper.readValue(序列化的objectMapper.typeFactory.ConstructParameterType(外部::class.java,内部::class.java))
assertEquals(42,已解析。内部。表示飞行)
}
}
使用Jackson的
2.9.6
,然后使用Jackson的主分支2.9.8
以及当前的Jackson Kotlin模块,我添加了这个测试用例,它通过了您的代码版本和更干净的代码惯用版本
请注意,我还将stringify
方法更新为更加惯用的方法,但这不会影响测试
您对readValue
的调用也比必要的调用复杂得多。更改:
val parsed = objectMapper.readValue<Outer<Inner>>(serialized, objectMapper.typeFactory.constructParametricType(Outer::class.java, Inner::class.java))
val parsed=objectMapper.readValue(序列化的objectMapper.typeFactory.ConstructParameterType(外部::class.java,内部::class.java))
简单地说:
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
val parsed=objectMapper.readValue(序列化)
这是完全通过测试:
class TestStackOverflow53499407 {
data class Inner(val meaningOfLife: Int)
data class Outer<T>(val inner: T)
fun <T> ObjectMapper.stringify(value: T, pretty: Boolean = false): String {
StringWriter().use { writer ->
if (pretty) {
writerWithDefaultPrettyPrinter().writeValue(writer, value)
} else {
writeValue(writer, value)
}
return writer.toString()
}
}
@Test
fun test53499407_cleanTest() {
val outer = Outer(Inner(42))
val objectMapper = jacksonObjectMapper()
val serialized = objectMapper.stringify(outer, true)
println(serialized)
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
assertEquals(42, parsed.inner.meaningOfLife)
}
@Test
fun test53499407_idiomatic_tweek() {
val outer = Outer(Inner(42))
val jsonFactory = JsonFactory()
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
jsonFactory.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
val objectMapper = ObjectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.propertyNamingStrategy = PropertyNamingStrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized = objectMapper.stringify(outer, true)
println(serialized)
// This line changed to be idiomatic
val parsed = objectMapper.readValue<Outer<Inner>>(serialized)
assertEquals(42, parsed.inner.meaningOfLife)
}
@Test
fun test53499407_as_written_in_stackoverflow() {
val outer = Outer(Inner(42))
val jsonFactory = JsonFactory()
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
jsonFactory.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
val objectMapper = ObjectMapper(jsonFactory)
objectMapper.findAndRegisterModules()
objectMapper.propertyNamingStrategy = PropertyNamingStrategy.SnakeCaseStrategy()
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
val serialized = objectMapper.stringify(outer, true)
println(serialized)
// deserializing does not work using:
// https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
val parsed = objectMapper.readValue<Outer<Inner>>(serialized, objectMapper.typeFactory.constructParametricType(Outer::class.java, Inner::class.java))
assertEquals(42, parsed.inner.meaningOfLife)
}
}
类TestStackOverflow53499407{
数据类内部(val意味着飞行:Int)
数据类外部(val内部:T)
stringify(值:T,pretty:Boolean=false):String{
StringWriter()。请使用{writer->
如果(漂亮){
writerWithDefaultPrettyPrinter().writeValue(writer,值)
}否则{
writeValue(writer,value)
}
return writer.toString()
}
}
@试验
趣味测试53499407_cleanTest(){
val外部=外部(内部(42))
弗吉尼亚州