在 Kotlin 中使用 Retrofit2 + SimpleXML:MethodException:注释必须标记为 set 或 get 方法

24
我想通过使用Kotlin中的Retrofit2 + SimpleXML从API获取XML数据并将其映射到Kotlin模型对象。但是,我从SimpleXML得到了以下错误消息。

org.simpleframework.xml.core.MethodException: 注释@org.simpleframework.xml.Element(data=false, name=, required=true, type=void)必须标记为设置或获取方法

这是获取的XML数据。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
    <result code="0">Success</result>
    <token>XXXXXXXXXXXXXXXXXXXX</token>
    <uid>4294967295</uid>
</response>

Kotlin模型对象如下:

@Root(name = "response")
public class User() {
    @Element public var result: String? = null
    @Element public var token: String? = null
    @Element public var uid: String? = null
}

以下是APIClient的内容。
interface  MyService {
    @GET("/testLogin.xml")
    fun getUser(): Call<User>
}

val retrofit = Retrofit.Builder()
        .baseUrl(baseURL)
        .addConverterFactory(SimpleXmlConverterFactory.create())
        .build()
val call = retrofit.create(MyService::class.java).getUser()
call.enqueue(object: Callback<User> {
        override fun onResponse(p0: Call<User>?, response: Response<User>?) {
            val response = response?.body()
        }
        override fun onFailure(p0: Call<User>?, t: Throwable?) {
            Log.e("APIClient", t?.message)
        }

我收到了HTTP状态码200和正确的XML数据,因此我认为我的模型对象声明存在问题。

可能是kotlin数据类 + bean验证JSR 303的重复问题。 - Jayson Minard
3个回答

32

这和以下问题是相同的:kotlin数据类+bean验证jsr 303

你需要使用注解使用点目标,因为属性上的注解默认优先级顺序为:

  • 参数如果在构造函数中声明
  • 属性如果目标允许,但只有Kotlin创建的注解才能做到这一点
  • 字段可能是这里发生的情况,这不是你想要的)。

使用getset目标将注解放置在getter或setter上。 这是getter的代码:

@Root(name = "response")
public class User() {
    @get:Element public var result: String? = null
    @get:Element public var token: String? = null
    @get:Element public var uid: String? = null
}

详细信息请查看链接的答案


9
感谢您的回答!我使用了 field:Element 注释,并且它已经很好地发挥作用了。 - c8112002
1
@get:Element 更改为 @field:Element 对我有用。 参考链接:https://dev59.com/zlYM5IYBdhLWcg3wgwXH#48790217 - Jim Andreas

4
To avoid the error in parse do one should place annotation tags @set e @get

@Root(name = "response", strict = false)
public class User() {

    @set:Element(name = "result")
    @get:Element(name = "result")
    public var result: String? = null

    @set:Element(name = "token")
    @get:Element(name = "token")
    @Element public var token: String? = null

    @set:Element(name = "uid")
    @get:Element(name = "uid")
    public var uid: String? = null
}

请阅读 https://stackoverflow.blog/2009/07/23/non-english-question-policy/ ... 您可以使用 https://pt.stackoverflow.com/? - Sᴀᴍ Onᴇᴌᴀ
有什么想法为什么这个能够工作吗?有没有办法简化这段代码? - blueberry_chopsticks

2

如果您不熟悉SimpleXml库,但如果它的注释处理器正在寻找特定的get和set方法,则可以尝试按照以下方式设置类:

@Root(name="response") class User() {
var result:String?=null
    @Element
    get
    @Element
    set
var token:String?=null
    @Element
    get
    @Element
    set
var uid:String?=null
    @Element
    get
    @Element
    set
}

另外,如果@Element注释支持字段类型,您可以使用以下方法:
@Root(name="response") class User() {
    @Element @JvmField var result:String?=null
    @Element @JvmField var token:String?=null
    @Element @JvmField var uid:String?=null
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接