I am trying to make a Post Request using Retrofit, MVVM, Coroutines and Hilt.
After sending the post request I get this error
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
(I have searched but none was helpful)
AppModule
@Provides @Singleton fun provideRetrofit(gson: Gson) : Retrofit = Retrofit.Builder() .baseUrl(EndPoints.BASE_URL) .client(OkHttpClient.Builder().also { client -> if (BuildConfig.DEBUG){ val logging = HttpLoggingInterceptor() logging.setLevel(HttpLoggingInterceptor.Level.BODY) client.addInterceptor(logging) } }.build() ) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .build() @Provides @Singleton fun provideApiService(retrofit: Retrofit) = retrofit.create(ApiService::class.java)
ApiService
@POST(EndPoints.REGISTER_WITH_EMAIL) suspend fun registerUserWithEmail(@Body newUser: NewUser) : Response<JsonResponse>
ApiDataSource
suspend fun createNewUserEmail(newUser: NewUser) = apiService.registerUserWithEmail(newUser)
NewUser
data class NewUser ( @SerializedName("username") val userName: String?, @SerializedName("password") val password: String?, @SerializedName("email") val email: String?, @SerializedName("birthday") val birthday: String?, @SerializedName("birth_year") val birthYear: String?, @SerializedName("fullname") val fullname: String?, @SerializedName("gender") val gender: String?)
RegisterRepo
suspend fun saveUserWithEmail(newUser: NewUser) = safeApiCall { apiDataSource.createNewUserEmail(newUser) }
RegisterViewModel
//SaveUserDetails private val _saveDetailsEmail = MutableLiveData<Resource<JsonResponse>>() fun doRegisterUserEmail(newUser: NewUser) = viewModelScope.launch { try { _saveDetailsEmail.value = registerRepo.saveUserWithEmail(newUser) } catch (exception: Exception){ } }
JsonResponse
data class JsonResponse (val success: String, val message: String)
RegisterFragment
val userDetails = NewUser(usernameString, passwordPassed, emailPassed, birthdayPassed, birthYearPassed, fullnameString, genderString) registerViewModel.doRegisterUserEmail(userDetails) registerViewModel.saveDetailsEmail.observe(viewLifecycleOwner, Observer { when(it.status){ Resource.Status.SUCCESS -> { if(it.data?.success == "0"){ //Display error Toast.makeText(requireContext(), it.data.message + "Registration", Toast.LENGTH_LONG ).show() } else if(it.data?.success == "1"){ //go to home activity Toast.makeText(requireContext(), it.data.message + "Registrationx", Toast.LENGTH_LONG ).show() val action = DetailsFragmentDirections.actionDetailsFragmentToHomeActivity() navController.navigate(action) } } Resource.Status.LOADING -> { //Show loading } Resource.Status.ERROR -> { Toast.makeText(requireContext(), it.toString(), Toast.LENGTH_LONG).show() } } }) }
This is the response after testing with POSTMAN. it was working
{"success":"1","message":"User details saved"}
Update RESOURCE class
data class Resource<out T>(val status: Status, val data: T?, val message: String?) { enum class Status { SUCCESS, ERROR, LOADING } companion object { fun <T> success(data: T): Resource<T> { return Resource(Status.SUCCESS, data, null) } fun <T> error(message: String, data: T? = null): Resource<T> { return Resource(Status.ERROR, data, message) } fun <T> loading(data: T? = null): Resource<T> { return Resource(Status.LOADING, data, null) } }
UPDATE – FULL LOGCAT
6:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: --> POST https://2e3045dc760e.ngrok.io/snappmi/account/register/register_with_email.php 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: Content-Type: application/json 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: Content-Length: 150 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: {"birth_year":"1999","birthday":"1999-09-20","email":"makanaki@gmail.com","fullname":"makanaki","gender":"Male","password":"yellow","username":"maka"} 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: --> END POST (150-byte body) 09-20 14:26:01.660 20137-20137/com.snappmi.snappmi W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView) 09-20 14:26:01.660 20137-20137/com.snappmi.snappmi W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView) 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <-- 200 https://2e3045dc760e.ngrok.io/snappmi/account/register/register_with_email.php (6500ms) 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: content-type: text/html; charset=UTF-8 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: date: Sun, 20 Sep 2020 13:27:07 GMT 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: server: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: x-powered-by: PHP/7.4.6 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: content-length: 1475 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: username in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>7</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: password in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>8</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: email in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>9</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: birthday in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>10</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: birth_year in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>11</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: fullname in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>12</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <b>Notice</b>: Undefined index: gender in <b>C:xampphtdocssnappmiaccountregisterregister_with_email.php</b> on line <b>13</b><br /> 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: <br /> }
PHP SCODE
if ($_SERVER['REQUEST_METHOD']=='POST'){ $username = $_POST['username']; $password = $_POST['password']; $email = $_POST['email']; $birthday = $_POST['birthday']; $birth_year = $_POST['birth_year']; $fullname = $_POST['fullname']; $gender = $_POST['gender']; $joined = date('Y/m/d H:i:s'); $hashed_password = password_hash($password, PASSWORD_DEFAULT); if(usernameExists($conn, $username)) { $result["success"] = "0"; $result["message"] = "Username already taken"; echo json_encode($result); } elseif(!usernameExists($conn, $username)){ $sql = "INSERT INTO users (username, password, email, birthday, birth_year, fullname, gender, joined) VALUES (?,?,?,?,?,?,?,?)"; $stmt= $conn->prepare($sql); $stmt->execute([$username, $hashed_password, $email, $birthday, $birth_year, $fullname, $gender, $joined]); if($stmt){ $result["success"] = "1"; $result["message"] = "success"; echo json_encode($result); } } else{ $result["success"] = "0"; $result["message"] = "An error occured" .mysqli_error($conn); echo json_encode($result); }
}
Advertisement
Answer
I had to decode the JSON sent to the server especially when the content type here is application/json
$data = file_get_contents('php://input'); $json_data = json_decode($data , true); //I added these above if ($_SERVER['REQUEST_METHOD']=='POST'){ $username = $json_data["username"]; $password = $json_data["password"]; $email = $json_data["email"]; }