Невозможно создать конвертер @Body для класса в Retrofit с помощью Moshi

У меня проблема с MoshiConverterFactory и Retrofit - я не могу отправить запрос POST JSON в RestAPI, потому что это всегда приводит к ошибке. Я мог бы успешно сделать это с помощью Multipart, но API не поддерживает это, поэтому об этом не может быть и речи ...

Мой одноэлементный объект, содержащий ссылку на службу:

object Singleton {
    val okhttp = OkHttpClient.Builder()
        .addInterceptor(HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        })
        .build()

    val moshi = Moshi.Builder().build()

    val retrofit = Retrofit.Builder()
        .baseUrl("https://some_shows_api.com/api/")
        .client(okhttp)
        .addConverterFactory(MoshiConverterFactory.create())
        .build()

    val service = retrofit.create(ShowsApiService::class.java)
}

Зарегистрируйте метод пользователя, который вызывает проблему в моей ViewModel:

    fun registerUser(email: String, password: String) {
        val authData = AuthData(email, password)
        Singleton.service.register(authData).enqueue(object : Callback<Register> {
            override fun onFailure(call: Call<Register>, t: Throwable) {
                // some errror implementation
            }

            override fun onResponse(call: Call<Register>, response: Response<Register>) {
                if (response.isSuccessful) {
                    val body = response.body()
                    if (body != null) {
                        // login user
                    } else {
                        // some error implementation
                    }
                }
            }
        })
    }

Мой интерфейс:

data class AuthData(
    val email: String,
    val password: String
)

interface ShowsApiService {
    @Headers("Content-Type: application/json")
    @POST("users")
    fun register(@Body authData: AuthData): Call<Register>
}

То, что я уже пытался сделать: добавление @field:Json() аннотаций к параметрам моего класса AuthData (ошибка все та же), передача данных с использованием multipart и form-url-кодирования (API не поддерживает это). Кто-нибудь видит, что я делаю не так? Я также не вижу в Интернете примеров людей, использующих Moshi с Retrofit ... Любая помощь или подсказка будут очень благодарны. Спасибо!

Ошибка:

FATAL EXCEPTION: main
    Process: com.frideriklab.android_course, PID: 7774
    java.lang.IllegalArgumentException: Unable to create @Body converter for class com.frideriklab.android_course.AuthData (parameter #1)
        for method ShowsApiService.login
        at retrofit2.Utils.methodError(Utils.java:52)
        at retrofit2.Utils.parameterError(Utils.java:57)
        at retrofit2.RequestFactory$Builder.parseParameterAnnotation(RequestFactory.java:735)
        at retrofit2.RequestFactory$Builder.parseParameter(RequestFactory.java:306)
        at retrofit2.RequestFactory$Builder.build(RequestFactory.java:193)
        at retrofit2.RequestFactory.parseAnnotations(RequestFactory.java:67)
        at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:26)
        at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
        at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy0.login(Unknown Source)
        at com.frideriklab.android_course.ShowsViewModel.loginUser(ShowsViewModel.kt:85)
        at com.frideriklab.android_course.AuthFragment$onViewCreated$3.onClick(AuthFragment.kt:56)
        at android.view.View.performClick(View.java:6669)
        at android.view.View.performClickInternal(View.java:6638)
        at android.view.View.access$3100(View.java:789)
        at android.view.View$PerformClick.run(View.java:26145)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.IllegalArgumentException: Cannot serialize Kotlin type com.frideriklab.android_course.AuthData. Reflective serialization of Kotlin classes without using kotlin-reflect has undefined and unexpected behavior. Please use KotlinJsonAdapter from the moshi-kotlin artifact or use code gen from the moshi-kotlin-codegen artifact.
        at com.squareup.moshi.ClassJsonAdapter$1.create(ClassJsonAdapter.java:83)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:138)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:98)
        at retrofit2.converter.moshi.MoshiConverterFactory.requestBodyConverter(MoshiConverterFactory.java:106)
        at retrofit2.Retrofit.nextRequestBodyConverter(Retrofit.java:282)
        at retrofit2.Retrofit.requestBodyConverter(Retrofit.java:262)
        at retrofit2.RequestFactory$Builder.parseParameterAnnotation(RequestFactory.java:732)

person friderik    schedule 17.11.2019    source источник


Ответы (1)


Я тоже никогда не использовал Моши. Но вы можете попробовать это как альтернативу.

@POST("users")
fun register(@Body authData: Map<String, String>): Call<Register>

И создайте карту, как показано ниже:

fun registerUser(email: String, password: String) {
    val authData = HashMap<String, String>()
    authData.put("email", email)
    authData.put("password", password)

    Singleton.service.register(authData).

    ...
}
person Md. Asaduzzaman    schedule 17.11.2019
comment
Привет @friderik, Вы пробовали это? - person Md. Asaduzzaman; 19.11.2019
comment
Ваше решение работает, спасибо! Я также решил это, передав объект AuthData, как и раньше, но добавив аннотацию @JsonClass(generateAdapter = true) перед объявлением класса. - person friderik; 21.11.2019