我正在尝试通过 Kotlin 使用 Jackson 来反序列化由 lastfm api 提供的 xml。我在 Java 中使用 JAXB 进行了此工作,并且正在尝试移植它。除了未包装的列表字段外,一切正常 - 下面示例中的 Track。我知道 Track 数据类正在工作,因为如果我使用 val track: Track? = null
而不是val track: List<Track>? = null
我确实得到了一个有效的单个 Track 对象。
我得到的错误是 com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of
info.eidson.lastfm.Track (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('Flash \Flash Gordon's Theme\""')
at [Source: (ByteArrayInputStream); line: 1, column: 205] (through reference chain: info.eidson.lastfm.RecentTracks["track"]->java.util.ArrayList[1])
我相信它正在尝试使用 List 类作为 POJO 而不是 Track。
我尝试使用常规类而不是具有相同结果的数据类。根据https://www.baeldung.com/jackson-xml-serialization-and-deserialization所需要做的就是添加 @JacksonXmlElementWrapper(useWrapping = false)
注解。我尝试过使用和不使用 @JacksoXmlProperty
注释,我尝试设置 useWrapping
在映射器上。
接下来我应该尝试什么?
object Api {
fun getRecentTracks(): RecentTracks {
val module = JacksonXmlModule()
module.setDefaultUseWrapper(false);
val xmlMapper = XmlMapper(module)
xmlMapper.registerKotlinModule()
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
xmlMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
val params = HashMap<String?, String?>()
params.put("user", "eidsonator")
val out = Http.getRequest("user.getrecenttracks", params)
val stream = ByteArrayInputStream(out.toByteArray())
return xmlMapper.readValue(stream, RecentTracks::class.java)
}
}
data class RecentTracks(
val user: String = "",
val page: Int = -1,
val perPage: Int = -1,
val totalPages: Int = -1,
val total: Int = -1,
@JacksonXmlProperty(localName = "track")
@JacksonXmlElementWrapper(useWrapping = false)
val track: List<Track>? = null
)
data class Track(
val name: String = "",
val artist: String = "",
val album: String = ""
)
<?xml version="1.0" encoding="UTF-8"?>
<recenttracks page="1" perPage="50" total="283105" totalPages="5663" user="eidsonator">
<track>
<artist mbid="">Rockit</artist>
<name>Flash \Flash Gordon's Theme\""</name>
<streamable>0</streamable>
<mbid/>
<album mbid="">Freddie Mercury Rework</album>
<url>https://www.last.fm/music/Rockit/_/Flash+%5CFlash+Gordon%27s+Theme%5C%22%22</url>
<image size="small">https://lastfm.freetls.fastly.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png</image>
<image size="medium">https://lastfm.freetls.fastly.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png</image>
<image size="large">https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png</image>
<image size="extralarge">https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png</image>
<date uts="1578532113">09 Jan 2020, 01:08</date>
</track>
<track>
<artist mbid="">A June & J Beat</artist>
<name>Irony</name>
<streamable>0</streamable>
<mbid>fa542ad6-ed2f-4ce6-ab4c-b2671cd916fa</mbid>
<album mbid="">Appetizers (Chillhop Presents)</album>
<url>https://www.last.fm/music/A+June+&+J+Beat/_/Irony</url>
<image size="small">https://lastfm.freetls.fastly.net/i/u/34s/6aded46748a466920f12854069d9226e.jpg</image>
<image size="medium">https://lastfm.freetls.fastly.net/i/u/64s/6aded46748a466920f12854069d9226e.jpg</image>
<image size="large">https://lastfm.freetls.fastly.net/i/u/174s/6aded46748a466920f12854069d9226e.jpg</image>
<image size="extralarge">https://lastfm.freetls.fastly.net/i/u/300x300/6aded46748a466920f12854069d9226e.jpg</image>
<date uts="1578531592">09 Jan 2020, 00:59</date>
</track>
<!-- 48 more tracks... -->
</recenttracks>
最佳答案
问题似乎是由您尝试获取此 XML 引起的:
<artist mbid="">Rockit</artist>
并将其反序列化为名为 artist
的单个字符串属性。 专辑
也是如此。 name
没问题,因为它没有 mbid
属性,但由于 artist
和 album
具有该属性,Jackson 无法直接将该 XML 元素反序列化为字符串,因为它不知道如何处理 mbid
。 (您可以通过删除 mbid
属性来检查这一点:一旦我这样做,反序列化就起作用了。)
Track
上的 artist
和 album
属性是否应该是对象本身,其中一个属性为 mbid
,另一个属性为 mbid
也许是文本的属性?
关于java - 通过 Kotlin 使用 Jackson 反序列化对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59664808/