Десериализовать список объектов с Джексоном через Kotlin - PullRequest
1 голос
/ 09 января 2020

Я пытаюсь использовать Джексона через Kotlin для десериализации xml, предоставленной API lastfm. У меня это работало в Java с JAXB, и я пытаюсь его портировать. Все работает, за исключением развернутых полей списка - отслеживание в примере ниже. Я знаю, что класс данных 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\&quot;&quot;') at [Source: (ByteArrayInputStream); line: 1, column: 205] (through reference chain: info.eidson.lastfm.RecentTracks["track"]->java.util.ArrayList[1]), и я считаю, что он пытается использовать класс List в качестве POJO вместо Track.

I ' мы попытались использовать обычный класс вместо класса данных с тем же результатом. Согласно 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\&quot;&quot;</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 &amp; 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+&amp;+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>

1 Ответ

1 голос
/ 10 января 2020

Кажется, проблема связана с тем, что вы пытаетесь взять это XML:

<artist mbid="">Rockit</artist>

и десериализовать его в одно строковое свойство с именем artist. То же самое касается album. Это нормально с name, так как у него нет атрибута mbid, но, поскольку artist и album имеют этот атрибут, Джексон не может напрямую десериализовать этот элемент XML в строку, так как он не ' не знаю, что делать с mbid. (Вы можете проверить это, удалив атрибут mbid: как только я это сделал, десериализация сработала.)

Если свойства artist и album на Track сами являются объектами, с свойство для mbid и другое свойство для текста, может быть?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...