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
在我的Android应用程序中,我想使用以头文件格式发送的令牌来获取用户配置文件的详细信息,但我得到了以下错误
Specify the JSON Parsing Error:
指定JSON解析错误:
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
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
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
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
<?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);
}
?>
call Postman Api Response
调用Postman API响应
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
)
更多回答
Handle the exception and log the JSON you're getting
处理异常并记录您得到的JSON
How should I do this?
我该怎么做呢?
Your error is sort of self-explanatory: 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. [...]
)
您的错误是不言而喻的:应该是BEGIN_OBJECT,但在第1行第2列路径上是Begin_ARRAY。您期望的是JSON对象(即{...}),但实际上您收到的是JSON对象的列表(即[...])
Thank you. Is the error related to api? Is there no way to solve the problem in Android?
谢谢。该错误是否与接口相关?有没有办法在安卓系统中解决这个问题?
@Noah; you can solve this by either adjusting your PHP code, or the Android app code. The cause for the EOFException
is 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. For Expected BEGIN_OBJECT but was BEGIN_ARRAY
as jujka pointed out, the JSON structure is incorrect. Please verify that your PHP code really always responds with a JSON object { ... }
.
@noah;您可以通过调整您的PHP代码或Android应用程序代码来解决这个问题。EOFException的原因可能是,当没有找到匹配的记录时,您的PHP代码会生成一个空响应。它应该生成有效的JSON(例如NULL)或发送HTTP4...表示有错误。对于预期的BEGIN_OBJECT,但正如jujka指出的那样是Begin_ARRAY,JSON结构是不正确的。请验证您的PHP代码是否真的总是使用JSON对象{...}进行响应。
我是一名优秀的程序员,十分优秀!