Reputation: 171
I am trying to implement user register on my app using Retrofit, i however keep getting this error not sure whats wrong, java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
This is the response from postman
{
"isSuccessful": true,
"message": "successful",
"user": {
"name": "Jackline Jazz",
"email": "[email protected]",
"phone": "000000"
}
}
I have two model classes the User model class
data class User(
val name: String,
val email:String,
val phone:String
)
And the login response class
data class LoginResponse(
val isSuccessful:Boolean,
val message: String,
val user: List<User>
)
my Retrofit object
object RetrofitClient {
private const val BASE_URL = "http://10.0.2.2:7000/"
val instance: RetrofitApi by lazy {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(RetrofitApi::class.java)
}
}
Retrofit api
@FormUrlEncoded
@POST("users/register")
fun userRegister(
@Field("name") name: String,
@Field("email") email: String,
@Field("password") password: String,
@Field("confirmPassword") confirmPassword: String
): Call<LoginResponse>
and my register class
RetrofitClient.instance.userRegister(name, email, password, confirmPassword)
.enqueue(object : Callback<LoginResponse> {
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
Toast.makeText(applicationContext, t.message, Toast.LENGTH_LONG).show()`
}
override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
if (response.body()?.isSuccessful!!){
val intent = Intent(applicationContext, MainActivity::class.java)
startActivity(intent)
}else{
Toast.makeText(applicationContext, response.body()?.message, Toast.LENGTH_LONG).show()
}
}
})
}
}
And if possible someone help me implement Kotlin coroutines
Upvotes: 1
Views: 306
Reputation: 1006514
In your previous question, you were hitting a users/login
endpoint. You created a LoginResponse
that modeled the response from the server. There, users/login
returns a List<User>
, so LoginResponse
had to be set up that way.
Now, you are hitting a users/register
endpoint... but you are still trying to use LoginResponse
. As you can see from your JSON, you are getting different JSON from the server, where there is only one user. As a result, you need a different response class (e.g., RegisterResponse
) that models this new response:
data class RegisterResponse(
val isSuccessful:Boolean,
val message: String,
val user: User
)
@FormUrlEncoded
@POST("users/register")
fun userRegister(
@Field("name") name: String,
@Field("email") email: String,
@Field("password") password: String,
@Field("confirmPassword") confirmPassword: String
): Call<RegisterResponse>
Upvotes: 3
Reputation: 6050
BEGIN_ARRAY
means there is some JSON returned that contains a JSON Array ([]
) where your object schema expects a JSON object ({}
).
Sometimes APIs return different responses based on the client they're dealing with, so it's better to debug the issue at hand in your code. One way of doing this would be to temporarily use Retrofit's scalar converter factory.
Add this dependency:
dependencies {
implementation 'com.squareup.retrofit2:converter-scalars:<your-retrofit-version>'
}
and this code
val retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
...
and return a Callable<String>
instead of your custom type and log what is actually returned from your server. Then you can act upon accordingly.
Upvotes: 0