In my Android application, I want to fetch the details of the user's profile using the token that is sent in the header format, but I get the following errors
Specify the JSON Parsing Error:
java.io.EOFException: End of input at line 1 column 1 path $ at com.google.gson.stream.JsonReader.nextNonWhite space(JsonReaderjaval 406) at com.google.gson.stream.JsonReader.consumeNonE xecutePrefix(JsonReaderjaval 615) at com.google.gson.stream.JsonReader.doPeek(JsonR eader.java.544) at com.google.gson.stream.JsonReader. peek(JsonRea derjava:435) at com.google.gson.internal.bind.ReflectiveTypeAdapt erFactory$Adapter.read(ReflectiveTypeAdapterFacto ry.java:251) at retrofit2.converter.gson.GsonResponseBodyConvert er.convert(GsonResponseBodyConverter.java:40) at retrofit2.convertergson.GsonResponseBodyConvert er. convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java: 243) at retrofit.2.0 kHttpCall$1.onResponse(OkHttpCall.java: 153) at okhttp3.internal.connection.RealCall$AsyncCall.run( RealCall.kt:519) at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1137) at lava i itil rnnr•I irrpnt ThrparlPnnIFvpri rtnrW/nrkpr n in(
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $ at com.google.gson.internal.bind.ReflectiveTypeAdapt erFactory$Adapter.read(ReflectiveTypeAdapterFacto ry.java:270) at retrofit2.converter.gson.GsonResponseBodyConvert erconvert(GsonResponseBodyConverterjava:40) at retrofit2.converter.gson.GsonResponseBodyConvert erconvert(GsonResponseBodyConverterjava:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java: 243) at retrofit2.0kHttpCall$1.onResponse(OkHttpCall.java: 153) at okhttp3.internal.connection.RealCall$AsyncCall.run( RealCall.kt:519) at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run( ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.javal 012) Suppressed: kotlinx.coroutines. DiagnosticCoroutineContextExcep tion: [StandaloneCoroutine{Cancelling}@acd6dc7, Dispatchers.Mainimmediate] Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at
Network Module
@Provides
@Singleton
fun provideInterceptor() = HttpLoggingInterceptor().apply {
level =
if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
}
@Provides
@Singleton
fun provideClient(
timeOut: Long,
@Named(NAMED_PING) ping: Long,
session: SessionManager,
interceptor: HttpLoggingInterceptor
) = OkHttpClient.Builder()
.addInterceptor { chain ->
val token = runBlocking {
session.getToken.first().toString()
}
chain.proceed(chain.request().newBuilder().also {
it.addHeader(AUTHORIZATION, "$token")
it.addHeader(ACCEPT, APPLICATION_JSON)
}.build())
}.also { client ->
client.addInterceptor(interceptor)
}
.writeTimeout(timeOut, TimeUnit.SECONDS)
.readTimeout(timeOut, TimeUnit.SECONDS)
.connectTimeout(timeOut, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.pingInterval(ping, TimeUnit.SECONDS)
.build()
@Provides
@Singleton
fun provideRetrofit(baseUrl: String, gson: Gson, client: OkHttpClient): ApiServices =
Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(ApiServices::class.java)
}
ApiService
@GET("profile/show_profile.php")
suspend fun getInfoUser(): Response<ResponseInfoUser>
ResponseInfoUser
import com.google.gson.annotations.SerializedName
data class ResponseInfoUser(
@field:SerializedName("date")
val date: String?, // 2023-09-02
@field:SerializedName("email")
val email: String?, //
@field:SerializedName("image")
val image: String?, //
@field:SerializedName("name_family")
val nameFamily: String? // mahdi
)
I also wrote in this way
data class ResponseInfoUser(
@SerializedName("date")
val date: String?, // 2023-09-02
@SerializedName("email")
val email: String?, //
@SerializedName("image")
val image: String?, //
@SerializedName("name_family")
val nameFamily: String? // mahdi
)
HomeRepository
class HomeRepository @Inject constructor(private val api: ApiServices) {
suspend fun getInfoUser() = api.getInfoUser()
}
MviHomeIntent
sealed class HomeIntent {
object ShowInfoUser :HomeIntent()
}
HomeState
sealed class HomeState {
object Idle : HomeState()
object LoadingProfile : HomeState()
data class ShowInfoUser(val profile: ResponseInfoUser) : HomeState()
object Empty : HomeState()
data class Error(val error: String) : HomeState()
}
HomeViewModel
@HiltViewModel
class HomeViewModel @Inject constructor(private val repository: HomeRepository) : ViewModel() {
//Login
val intentChannel = Channel<HomeIntent>()
private val _state = MutableStateFlow<HomeState>(HomeState.Idle)
val state: StateFlow<HomeState> get() = _state
init {
handleIntents()
}
private fun handleIntents() = viewModelScope.launch {
intentChannel.consumeAsFlow().collect { intent ->
when (intent) {
is HomeIntent.ShowInfoUser -> fetchingProfileUser()
}
}
}
private fun fetchingProfileUser() = viewModelScope.launch {
val response = repository.getInfoUser()
_state.emit(HomeState.LoadingProfile)
when (response.code()) {
in 200..202 -> {
_state.emit(HomeState.ShowInfoUser(response.body()!!))
}
in 400..499 -> {
_state.emit(HomeState.Error(""))
}
in 500..599 -> {
_state.emit(HomeState.Error(""))
}
}
}
}
BackEnd PHP
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require '../connection.php';
$rawToken = $_SERVER['HTTP_AUTHORIZATION'];
$token = preg_replace('/Bearer\s+|\[|\]/i', '', $rawToken);
$sql="SELECT * FROM tbl_subscribers WHERE token= :token";
$resault=$connect->prepare($sql);
$resault->bindParam(':token', $token);
$resault->execute();
while($row=$resault->fetch(PDO::FETCH_ASSOC)){
$record["name_family"]=$row['name_family'];
$record["email"]=$row['email'];
$record["date"]=$row['date'];
$record["image"]=$row['image'];
}
echo JSON_encode($record);
}
?>
I also changed the received response for the data class, but the error was not fixed
data class ResponseInfoUser(
@SerializedName("date")
val date: String, // 2023-08-27
@SerializedName("email")
val email: String, //
@SerializedName("image")
val image: String, // http
@SerializedName("name_family")
val nameFamily: String // dggf
)
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path. You expect a JSON object (i.e.{...}), but actually you receive a List of JSON objects (i.e.[...])EOFExceptionis probably that your PHP code produces an empty response when no matching record is found. It should either produce valid JSON (e.g.null) or send HTTP 4... to indicate an error. ForExpected BEGIN_OBJECT but was BEGIN_ARRAYas jujka pointed out, the JSON structure is incorrect. Please verify that your PHP code really always responds with a JSON object{ ... }.