Retrofit2 + SimpleXML в Kotlin: MethodException: аннотация должна отмечать набор или метод get

Я хочу получить XML-данные из API и сопоставить их с объектом модели Kotlin с помощью Retrofit2 + SimpleXML в Kotlin.

Однако я получил следующее сообщение об ошибке от SimpleXML.

org.simpleframework.xml.core.MethodException: Annotation @org.simpleframework.xml.Element(data = false, name=, required = true, type = void) должен отмечать набор или метод get

Это извлеченные данные XML

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

Объект модели Котлин ниже

@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. Поэтому я думаю, что мое объявление объекта модели является проблемой.

Ответы

Ответ 1

Это та же проблема, что и: класс данных kotlin + bean проверка jsr 303

Вам нужно использовать цели использования целевого объекта аннотации, поскольку по умолчанию для аннотации свойства присваивается приоритет как:

  • параметр (если объявлено в конструкторе)
  • свойство (если целевой сайт разрешает, но только созданные Kotlin аннотации могут это сделать)
  • поле (вероятно, что здесь произошло, чего вы не хотели).

Используйте get или set цель, чтобы поместить аннотацию на геттер или сеттер. Вот он для геттера:

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

Подробнее см. ответ..

Ответ 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
}

Ответ 3

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
}