我试图通过 retrofit 2来使用SimpleXML.在与Kotlin抗争了几个小时后,我决定try Java版本,然后将其转换为Kotlin.Java版本运行良好...

错误:

java.lang.RuntimeException: org.simpleframework.xml.core.MethodException: Annotation @org.simpleframework.xml.ElementList(data=false, empty=true, entry=, inline=true, name=entry, required=true, type=void) must mark a set or get method

I need a Kotlin model class that will be able to consume that XML. Here's input:

<feed>
   <entry>
        <id> someid </id>
        <published> somedate </published>
   </entry>

   <entry>
        <id> someid2 </id>
        <published> somedate2 </published>
   </entry>
</feed>

Java model class version (works fine):

@Root(name = "feed", strict = false)
public class MFeed {
    @ElementList(name = "entry", inline = true)
    private List<MEntry> entriesList;

    public MFeed(List<MEntry> entriesList) {
        this.entriesList = entriesList;
    }

    public MFeed() {
    }

    public List<MEntry> getEntriesList() {
        return entriesList;
    }

    public void setEntriesList(List<MEntry> entriesList) {
    this.entriesList = entriesList;
    }
}

@Root(name = "entry", strict = false)
public class MEntry {

    @Element(name = "id")
    private String id;

    @Element(name = "published")
    private String published;

    public MEntry() {
    }

    public MEntry(String id, String published) {
        this.id = id;
        this.published = published;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPublished() {
        return published;
    }

    public void setPublished(String published) {
        this.published = published;
    }
}

and autogenerated Kotlin models look like this:

@Root(name = "feed", strict = false)
class Feed {
    @ElementList(name = "entry", inline = true)
    private var entriesList: List<MEntry>? = null

    //autogenerated by converter java -> kotlin
    constructor(entriesList: List<MEntry>) {
        this.entriesList = entriesList
    }

    //autogenerated by converter java -> kotlin
    constructor() {}
}

@Root(name = "entry", strict = false)
class Entry {
    @Element(name = "id")
    var id: String? = null

    @Element(name = "published")
    var published: String? = null

    //autogenerated by converter java -> kotlin
    constructor() {}

    //autogenerated by converter java -> kotlin
    constructor(id: String, published: String) {
        this.id = id
        this.published = published
    }
}

I've serfed a lot for consuming XML lists including this post, this and this. None worked. Perhaps they are obsolete. Anyone faced such problem?

推荐答案

Try to add @field to your annotation @Element*. And you may move properties to constructor and also you could add data modifier to your classes. Like this:

@Root(name = "feed", strict = false)
data class Feed(
        @field:ElementList(name = "entry", inline = true)
        var entriesList: List<Entry>? = null
)

@Root(name = "entry", strict = true)
data class Entry(
        @field:Element(name = "id")
        var id: String? = null,

        @field:Element(name = "published")
        var published: String? = null
)

通过这一点,我成功地反序列化了xml:

import org.simpleframework.xml.Element
import org.simpleframework.xml.ElementList
import org.simpleframework.xml.Root
import org.simpleframework.xml.core.Persister

private val testXml = """
<feed>
   <entry>
        <id> someid </id>
        <published> somedate </published>
   </entry>

   <entry>
        <id> someid2 </id>
        <published> somedate2 </published>
   </entry>
</feed>
""".trimIndent()

@Root(name = "feed", strict = false)
data class Feed(
        @field:ElementList(name = "entry", inline = true)
        var entriesList: List<Entry>? = null
)

@Root(name = "entry", strict = true)
data class Entry(
        @field:Element(name = "id")
        var id: String? = null,

        @field:Element(name = "published")
        var published: String? = null
)

fun main(args: Array<String>) {
    println(testXml)

    val serializer = Persister()

    val example = serializer.read(Feed::class.java, testXml)

    println(example)
}

Kotlin相关问答推荐

Lambda和普通Kotlin函数有什么区别?

在kotlin中使用List(mylist. size){index—TODO()}或Map迭代>

Kotlin-删除按钮周围的空格

kotlin 模式匹配如何像 scala 一样工作

根据字符串值动态过滤数组列表 - kotlin

Kotlin 数据类中的大量参数

为 Gradle 子项目配置 Kotlin 扩展

Moshi:解析单个对象或对象列表(kotlin)

具有多个不同类型来源的 LiveData

如何在 android jetpack compose 中相互重叠列表项?

API 'variant.getJavaCompile()' 已过时

为什么 Dialog 没有 NavController [Missing]?

在用Kotlin编写的Android库公共API中处理R8+JvmStatic Annotation+Lambda

Kotlin中的测试无法访问受保护(protected)的方法

Kotlin 的 Double.toInt() 中使用了哪种方法,舍入还是截断?

TypeConverter()在Android的TypeConverter错误中具有私有访问权限

Kotlin reflect proguard SmallSortedMap

WebFlux 功能:如何检测空 Flux 并返回 404?

使用 Moshi/Retrofit2 访问深度嵌套的 JSON 数组

如何在 IntelliJ IDEA 中禁用粘贴时将 Java 转换为 Kotlin?