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

huangapple go评论112阅读模式
英文:

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

问题

我正在尝试使用 Retrofit、MVVM、Coroutines 和 Hilt 发送一个 POST 请求。

在发送 POST 请求后,我得到了以下错误:

java.lang.IllegalStateException: 预期的是对象(BEGIN_OBJECT),但在第 1 行第 1 列找到了字符串(STRING),路径为 $

(我已经搜索过了,但没有找到有帮助的解决方法)

AppModule

  1. @Provides
  2. @Singleton
  3. fun provideRetrofit(gson: Gson): Retrofit = Retrofit.Builder()
  4. .baseUrl(EndPoints.BASE_URL)
  5. .client(
  6. OkHttpClient.Builder().apply {
  7. if (BuildConfig.DEBUG) {
  8. val logging = HttpLoggingInterceptor()
  9. logging.level = HttpLoggingInterceptor.Level.BODY
  10. addInterceptor(logging)
  11. }
  12. }.build()
  13. )
  14. .addConverterFactory(ScalarsConverterFactory.create())
  15. .addConverterFactory(GsonConverterFactory.create(gson))
  16. .build()
  17. @Provides
  18. @Singleton
  19. fun provideApiService(retrofit: Retrofit) = retrofit.create(ApiService::class.java)

ApiService

  1. @POST(EndPoints.REGISTER_WITH_EMAIL)
  2. suspend fun registerUserWithEmail(@Body newUser: NewUser): Response<JsonResponse>

ApiDataSource

  1. suspend fun createNewUserEmail(newUser: NewUser) = apiService.registerUserWithEmail(newUser)

NewUser

  1. data class NewUser(
  2. @SerializedName("username") val userName: String?,
  3. @SerializedName("password") val password: String?,
  4. @SerializedName("email") val email: String?,
  5. @SerializedName("birthday") val birthday: String?,
  6. @SerializedName("birth_year") val birthYear: String?,
  7. @SerializedName("fullname") val fullname: String?,
  8. @SerializedName("gender") val gender: String?
  9. )

RegisterRepo

  1. suspend fun saveUserWithEmail(newUser: NewUser) = safeApiCall {
  2. apiDataSource.createNewUserEmail(newUser)
  3. }

RegisterViewModel

  1. // SaveUserDetails
  2. private val _saveDetailsEmail = MutableLiveData<Resource<JsonResponse>>()
  3. fun doRegisterUserEmail(newUser: NewUser) = viewModelScope.launch {
  4. try {
  5. _saveDetailsEmail.value = registerRepo.saveUserWithEmail(newUser)
  6. } catch (exception: Exception) {
  7. // Handle exception
  8. }
  9. }

JsonResponse

  1. data class JsonResponse(val success: String, val message: String)

RegisterFragment

  1. val userDetails = NewUser(usernameString, passwordPassed, emailPassed, birthdayPassed, birthYearPassed, fullnameString, genderString)
  2. registerViewModel.doRegisterUserEmail(userDetails)
  3. registerViewModel.saveDetailsEmail.observe(viewLifecycleOwner, Observer {
  4. when (it.status) {
  5. Resource.Status.SUCCESS -> {
  6. if (it.data?.success == "0") {
  7. // Display error
  8. Toast.makeText(requireContext(), it.data.message + "Registration", Toast.LENGTH_LONG).show()
  9. } else if (it.data?.success == "1") {
  10. // Go to home activity
  11. Toast.makeText(requireContext(), it.data.message + "Registrationx", Toast.LENGTH_LONG).show()
  12. val action = DetailsFragmentDirections.actionDetailsFragmentToHomeActivity()
  13. navController.navigate(action)
  14. }
  15. }
  16. Resource.Status.LOADING -> {
  17. // Show loading
  18. }
  19. Resource.Status.ERROR -> {
  20. Toast.makeText(requireContext(), it.toString(), Toast.LENGTH_LONG).show()
  21. }
  22. }
  23. })

RESOURCE 类更新

  1. data class Resource<out T>(val status: Status, val data: T?, val message: String?) {
  2. enum class Status {
  3. SUCCESS,
  4. ERROR,
  5. LOADING
  6. }
  7. companion object {
  8. fun <T> success(data: T): Resource<T> {
  9. return Resource(Status.SUCCESS, data, null)
  10. }
  11. fun <T> error(message: String, data: T? = null): Resource<T> {
  12. return Resource(Status.ERROR, data, message)
  13. }
  14. fun <T> loading(data: T? = null): Resource<T> {
  15. return Resource(Status.LOADING, data, null)
  16. }
  17. }
  18. }

这是使用 POSTMAN 测试后的响应,它是正常工作的:

  1. {"success":"1","message":"User details saved"}

UPDATE - 完整 LOGCAT

(这里是日志信息,包含了发送请求和响应的信息)

PHP 代码

(这里是 PHP 代码,用于处理 POST 请求并将数据存储到数据库)

英文:

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

  1. @Provides
  2. @Singleton
  3. fun provideRetrofit(gson: Gson) : Retrofit = Retrofit.Builder()
  4. .baseUrl(EndPoints.BASE_URL)
  5. .client(OkHttpClient.Builder().also { client -&gt;
  6. if (BuildConfig.DEBUG){
  7. val logging = HttpLoggingInterceptor()
  8. logging.setLevel(HttpLoggingInterceptor.Level.BODY)
  9. client.addInterceptor(logging)
  10. }
  11. }.build()
  12. )
  13. .addConverterFactory(ScalarsConverterFactory.create())
  14. .addConverterFactory(GsonConverterFactory.create(gson))
  15. .build()
  16. @Provides
  17. @Singleton
  18. fun provideApiService(retrofit: Retrofit) = retrofit.create(ApiService::class.java)

ApiService

  1. @POST(EndPoints.REGISTER_WITH_EMAIL)
  2. suspend fun registerUserWithEmail(@Body newUser: NewUser) : Response&lt;JsonResponse&gt;

ApiDataSource

  1. suspend fun createNewUserEmail(newUser: NewUser) = apiService.registerUserWithEmail(newUser)

NewUser

  1. data class NewUser (
  2. @SerializedName(&quot;username&quot;) val userName: String?,
  3. @SerializedName(&quot;password&quot;) val password: String?,
  4. @SerializedName(&quot;email&quot;) val email: String?,
  5. @SerializedName(&quot;birthday&quot;) val birthday: String?,
  6. @SerializedName(&quot;birth_year&quot;) val birthYear: String?,
  7. @SerializedName(&quot;fullname&quot;) val fullname: String?,
  8. @SerializedName(&quot;gender&quot;) val gender: String?)

RegisterRepo

  1. suspend fun saveUserWithEmail(newUser: NewUser) = safeApiCall {
  2. apiDataSource.createNewUserEmail(newUser) }

RegisterViewModel

  1. //SaveUserDetails
  2. private val _saveDetailsEmail = MutableLiveData&lt;Resource&lt;JsonResponse&gt;&gt;()
  3. fun doRegisterUserEmail(newUser: NewUser) = viewModelScope.launch {
  4. try {
  5. _saveDetailsEmail.value = registerRepo.saveUserWithEmail(newUser)
  6. }
  7. catch (exception: Exception){
  8. }
  9. }

JsonResponse

  1. data class JsonResponse (val success: String, val message: String)

RegisterFragment

  1. val userDetails = NewUser(usernameString, passwordPassed, emailPassed, birthdayPassed, birthYearPassed, fullnameString, genderString)
  2. registerViewModel.doRegisterUserEmail(userDetails)
  3. registerViewModel.saveDetailsEmail.observe(viewLifecycleOwner, Observer {
  4. when(it.status){
  5. Resource.Status.SUCCESS -&gt; {
  6. if(it.data?.success == &quot;0&quot;){
  7. //Display error
  8. Toast.makeText(requireContext(), it.data.message + &quot;Registration&quot;, Toast.LENGTH_LONG ).show()
  9. }
  10. else if(it.data?.success == &quot;1&quot;){
  11. //go to home activity
  12. Toast.makeText(requireContext(), it.data.message + &quot;Registrationx&quot;, Toast.LENGTH_LONG ).show()
  13. val action = DetailsFragmentDirections.actionDetailsFragmentToHomeActivity()
  14. navController.navigate(action)
  15. }
  16. }
  17. Resource.Status.LOADING -&gt; {
  18. //Show loading
  19. }
  20. Resource.Status.ERROR -&gt; {
  21. Toast.makeText(requireContext(), it.toString(), Toast.LENGTH_LONG).show()
  22. }
  23. }
  24. })
  25. }

This is the response after testing with POSTMAN. it was working

  1. {&quot;success&quot;:&quot;1&quot;,&quot;message&quot;:&quot;User details saved&quot;}

Update RESOURCE class

  1. data class Resource&lt;out T&gt;(val status: Status, val data: T?, val message: String?) {
  2. enum class Status {
  3. SUCCESS,
  4. ERROR,
  5. LOADING
  6. }
  7. companion object {
  8. fun &lt;T&gt; success(data: T): Resource&lt;T&gt; {
  9. return Resource(Status.SUCCESS, data, null)
  10. }
  11. fun &lt;T&gt; error(message: String, data: T? = null): Resource&lt;T&gt; {
  12. return Resource(Status.ERROR, data, message)
  13. }
  14. fun &lt;T&gt; loading(data: T? = null): Resource&lt;T&gt; {
  15. return Resource(Status.LOADING, data, null)
  16. }
  17. }

UPDATE - FULL LOGCAT

  1. 6:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: --&gt; POST
  2. https://2e3045dc760e.ngrok.io/snappmi/account/register/register_with_email.php
  3. 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: Content-Type: application/json
  4. 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: Content-Length: 150
  5. 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: {&quot;birth_year&quot;:&quot;1999&quot;,&quot;birthday&quot;:&quot;1999-09-20&quot;,&quot;email&quot;:&quot;makanaki@gmail.com&quot;,&quot;fullname&quot;:&quot;makanaki&quot;,&quot;gender&quot;:&quot;Male&quot;,&quot;password&quot;:&quot;yellow&quot;,&quot;username&quot;:&quot;maka&quot;}
  6. 09-20 14:26:01.640 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: --&gt; END POST (150-byte body)
  7. 09-20 14:26:01.660 20137-20137/com.snappmi.snappmi W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView)
  8. 09-20 14:26:01.660 20137-20137/com.snappmi.snappmi W/DisplayListCanvas: DisplayListCanvas is started on unbinded RenderNode (without mOwningView)
  9. 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;-- 200 https://2e3045dc760e.ngrok.io/snappmi/account/register/register_with_email.php (6500ms)
  10. 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: content-type: text/html; charset=UTF-8
  11. 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: date: Sun, 20 Sep 2020 13:27:07 GMT
  12. 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
  13. 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: x-powered-by: PHP/7.4.6
  14. 09-20 14:26:08.140 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: content-length: 1475
  15. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  16. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: username in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;7&lt;/b&gt;&lt;br /&gt;
  17. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  18. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: password in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;8&lt;/b&gt;&lt;br /&gt;
  19. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  20. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: email in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;9&lt;/b&gt;&lt;br /&gt;
  21. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  22. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: birthday in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;10&lt;/b&gt;&lt;br /&gt;
  23. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  24. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: birth_year in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;11&lt;/b&gt;&lt;br /&gt;
  25. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  26. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: fullname in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;12&lt;/b&gt;&lt;br /&gt;
  27. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  28. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;b&gt;Notice&lt;/b&gt;: Undefined index: gender in &lt;b&gt;C:\xampp\htdocs\snappmi\account\register\register_with_email.php&lt;/b&gt; on line &lt;b&gt;13&lt;/b&gt;&lt;br /&gt;
  29. 09-20 14:26:08.150 20137-20305/com.snappmi.snappmi I/okhttp.OkHttpClient: &lt;br /&gt;
  30. }

PHP SCODE

  1. if ($_SERVER[&#39;REQUEST_METHOD&#39;]==&#39;POST&#39;){
  2. $username = $_POST[&#39;username&#39;];
  3. $password = $_POST[&#39;password&#39;];
  4. $email = $_POST[&#39;email&#39;];
  5. $birthday = $_POST[&#39;birthday&#39;];
  6. $birth_year = $_POST[&#39;birth_year&#39;];
  7. $fullname = $_POST[&#39;fullname&#39;];
  8. $gender = $_POST[&#39;gender&#39;];
  9. $joined = date(&#39;Y/m/d H:i:s&#39;);
  10. $hashed_password = password_hash($password, PASSWORD_DEFAULT);
  11. if(usernameExists($conn, $username))
  12. {
  13. $result[&quot;success&quot;] = &quot;0&quot;;
  14. $result[&quot;message&quot;] = &quot;Username already taken&quot;;
  15. echo json_encode($result);
  16. }
  17. elseif(!usernameExists($conn, $username)){
  18. $sql = &quot;INSERT INTO users (username, password, email, birthday, birth_year, fullname, gender, joined) VALUES (?,?,?,?,?,?,?,?)&quot;;
  19. $stmt= $conn-&gt;prepare($sql);
  20. $stmt-&gt;execute([$username, $hashed_password, $email, $birthday, $birth_year, $fullname, $gender, $joined]);
  21. if($stmt){
  22. $result[&quot;success&quot;] = &quot;1&quot;;
  23. $result[&quot;message&quot;] = &quot;success&quot;;
  24. echo json_encode($result);
  25. }
  26. }
  27. else{
  28. $result[&quot;success&quot;] = &quot;0&quot;;
  29. $result[&quot;message&quot;] = &quot;An error occured&quot; .mysqli_error($conn);
  30. echo json_encode($result);
  31. }

}

答案1

得分: 1

我必须解码发送到服务器的 JSON 数据,特别是在这里内容类型为 application/json 时。

  1. $data = file_get_contents('php://input');
  2. $json_data = json_decode($data, true);
  3. // 我在上面添加了这些
  4. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  5. $username = $json_data["username"];
  6. $password = $json_data["password"];
  7. $email = $json_data["email"];
  8. }
英文:

I had to decode the JSON sent to the server especially when the content type here is application/json

  1. $data = file_get_contents(&#39;php://input&#39;);
  2. $json_data = json_decode($data , true);
  3. //I added these above
  4. if ($_SERVER[&#39;REQUEST_METHOD&#39;]==&#39;POST&#39;){
  5. $username = $json_data[&quot;username&quot;];
  6. $password = $json_data[&quot;password&quot;];
  7. $email = $json_data[&quot;email&quot;];
  8. }

huangapple
  • 本文由 发表于 2020年9月20日 16:17:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63976924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定