Skip to content
Advertisement

Retrofit Post Request Error – java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $

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"];

}

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement