Retrofit2 + SimpleXML in Kotlin: MethodException: Annotation must mark a set or get method

半腔热情 提交于 2019-11-27 11:49:16

问题


I want to fetch XML data from API and map it to Kotlin model object by using Retrofit2 + SimpleXML in Kotlin.

However, I got such as the following error message from SimpleXML.

org.simpleframework.xml.core.MethodException: Annotation @org.simpleframework.xml.Element(data=false, name=, required=true, type=void) must mark a set or get method

This is fetched XML data

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
    <result code="0">Success</result>
    <token>XXXXXXXXXXXXXXXXXXXX</token>
    <uid>4294967295</uid>
</response>

Kotlin model object is below

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

and APIClient is as follows.

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)
        }

I got HTTP status code 200 and correct XML data. So I think my declaration of model object is problem.


回答1:


This is the same problem as: kotlin data class + bean validation jsr 303

You need to use Annotation use-site targets since the default for an annotation on a property is prioritized as:

  • parameter (if declared in constructor)
  • property (if the target site allows, but only Kotlin created annotations can do this)
  • field (likely what happened here, which isn't what you wanted).

Use get or set target to place the annotation on the getter or setter. Here it is for the 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
}

See the linked answer for the details.




回答2:


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
}



回答3:


Not familiar with the SimpleXml library but if it's annotation processor is looking for specific get and set methods you may want to try setting up your class in the following way:

@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
}

As well, if the @Element annotation supports field types you could use this approach:

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


来源:https://stackoverflow.com/questions/35913391/retrofit2-simplexml-in-kotlin-methodexception-annotation-must-mark-a-set-or

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!