Retrofit2 错误 java.io.EOFException:第 1 行第 1 列输入结束

问题描述 投票:0回答:8

我使用 Retrofit2 调用了 PATCH Web 服务,但未调用 onResponse,而是调用了 onFailure 尽管服务的操作在服务器端成功了 完美

每当我尝试使用 fiddler 检查服务的工作情况时,我发现问题是序列化服务的即将到来的响应,并且当使用 fiddler 时,我发现 JSON 响应没有内容,因此 Retrofit 服务假设其失败因为没有内容并且无法序列化 EMPTY 内容 并给我这个错误

java.io.EOFException: End of input at line 1 column 1

Fiddler 原始响应

HTTP/1.1 200 OK
Server: nginx/1.9.4
Date: Wed, 02 Mar 2016 09:55:55 GMT
Content-Type: application/json
Content-Length: 0
Connection: close
Status: 200 OK
X-Content-Type-Options: nosniff

Fiddler Json 响应为空

java 中的网络服务

Call<Object> call = TimeCapp.services.accept_invited_alerts(HomeActivity.api_token, alert_id);

call.enqueue(new Callback<Object>()
{
    @Override
    public void onResponse (Call<Object> call, Response<Object> response)
    {
        if (response.isSuccess()) {
            String x = response.body();
        }
    }
    @Override
    public void onFailure (Call<Object>call, Throwable t)
    {
        String x = t.getMessage();//java.io.EOFException: End of input at line 1 column 1
    }
}

我尝试用 String、JsonObject、emptyCalssBody 替换 object .... 但失败了

网络服务接口

@PATCH("alerts/{alert_id}/accept")
Call<Object> accept_invited_alerts(@Header("X-Api-Token") String  
api_token, @Path("alert_id") int alert_id);
android web-services retrofit2
8个回答
131
投票

如果主体为空,则返回 void

@PATCH("alerts/{alert_id}/accept") Call<Void> accept_invited_alerts(@Header("X-Api-Token") String api_token, @Path("alert_id") int alert_id);

对于 Rx java 的改造,你可以使用这样的东西

@PATCH("alerts/{alert_id}/accept") Observable<Response<Void>> accept_invited_alerts(@Header("X-Api-Token") String api_token, @Path("alert_id") int alert_id);

编辑:对于 kotlin

@PATCH("alerts/{alert_id}/accept")
fun accept_invited_alerts(@Header("X-Api-Token")  api_token: String, @Path("alert_id") alert_id: Int): Call<Unit>

@PATCH("alerts/{alert_id}/accept")
fun accept_invited_alerts(@Header("X-Api-Token") api_token: String, @Path("alert_id") alert_id: Int): Observable<Response<Unit>>

28
投票

您可以创建 NullOnEmptyConverterFactory.class :

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;


public class NullOnEmptyConverterFactory extends Converter.Factory {

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        final Converter<ResponseBody, ?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
        return new Converter<ResponseBody, Object>() {
            @Override
            public Object convert(ResponseBody body) throws IOException {
                if (body.contentLength() == 0) return null;
                return delegate.convert(body);               
            }
        };
    }
}

并添加到代码创建中。例如:

 UploadImageNghiemThuApi uploadService = new Retrofit.Builder()
            .baseUrl(Config.URL+"/")
            .client(okHttpClient)
            // -----add here-------
            .addConverterFactory(new NullOnEmptyConverterFactory())
            //---------------------
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(UploadImageNghiemThuApi.class);

希望它可以帮助您解决问题。 谢谢!

编辑!!!

对于 kotlin 用例,你可以检查这个

class NullOnEmptyConverterFactory : Converter.Factory() {
override fun responseBodyConverter(
    type: Type,
    annotations: Array<Annotation>,
    retrofit: Retrofit
): Converter<ResponseBody, *> {
    val delegate: Converter<ResponseBody, *> =
        retrofit.nextResponseBodyConverter<Any>(this, type, annotations)
    return Converter { body -> if (body.contentLength() == 0L) null else delegate.convert(body) }
}

}


6
投票

非常感谢。

API

@FormUrlEncoded
@POST("/rebu/insertusuario.php")
Call<Void> insertLogin(
        @Field("email") String email,
        @Field("senha") String senha,
        @Field("codCondutor") Long codCondutor
);

班级:

Call call = service.insertLogin(login.getEmail(), login.getSenha(), login.getCodCondutor());

0
投票

对于我来说,在 Laravel 中,我在功能完成后没有发送任何响应,只需在服务器端添加以下行有所帮助。这可以适应您正在使用的语言。 只需从服务器端发送一些响应即可。

use Response;

return Response::json(array(
            'result' => 'success',

        ));

0
投票

我在 Spring Boot 服务中遇到了类似的问题。 问题在于 Content-Length 标头值。超过指定字节数的任何内容都会导致问题。

删除标题后,问题得到解决。

您可以删除标题或尝试使用一个很大的值。


0
投票

解决这种(Retrofit2 error java.io.EOFException: End of input at line 1 column 1)异常,即空体异常。你需要穿越虚空。

  private void callCheck(){

    Api api = service.getTestClient().create(Api.class);

    Call<Void> call = api.SendRequest(Constant.client_id,Constant.client_secret,Constant.apiUserName);;

    call.enqueue(new Callback<Void>() {
        @Override
        public void onResponse(Call<Void> call, retrofit2.Response<Void> response) {

            if (response.isSuccessful()) {
               //Perform according to it...
               // Here I am getting the response from the header...
            } else {
            // Is to handle the error body if an user provided the wrong values in the header...
                try {
           //these are for the error body
                    JSONObject jsonObject =new JSONObject(response.errorBody().string());
                    Log.d("ErrorBody:", jsonObject.toString());


                   JSONObject responseObj = jsonObject.getJSONObject("fault");
                    String fault = responseObj.getString("faultstring");
                    Log.d(TAG, "Fault: " + fault);

                    JSONObject responseObjDetail = responseObj.getJSONObject("detail");
                    String detail = responseObjDetail.getString("errorcode");
                    Log.d(TAG, "Detail: " + detail);
                }catch (JSONException | IOException e) {e.printStackTrace();}

            }
        }

0
投票

如果您尝试使用 Retrofit Result 类(如

Single<Result<Void>>
中所示),但您的代码可能错误地使用了 kotlin.Result 类,而不是使用 Retrofit2.adapter.rxjava2.Result 类,则在 Kotlin 中可能会发生此错误。

如果这是问题所在,请添加导入行

import retrofit2.adapter.rxjava2.Result
,以便您的代码将为结果使用正确的类。


0
投票
    I have been facing the same issue for such days and I checked this solution -
    
    You can get this error when you are expecting an object in the response, but the API doesn't return anything other than result codes (200,...). Options: - Check that the API returns a ServerResponse. - If you don't need it to return anything, use Observable<Response<Void>> instead of Observable<ServerResponse>
    
    
    this is my old working face with this issue Log : AddTaskError - End of input at line 1 column 1 - 
    
       @POST("/Api/AddUpdateTask")
            fun addUpdateTask(
                @Header("Content-Type") contentType: String?,
                @Header("SessionId") session: String?,
                @Body requestBody: RequestBody
            ): Call<JsonObject>
    
    and this is my method -
    private fun addTaskApi() {
            try {
                customProgress?.show("")
            } catch (e: BadTokenException) {
                e.printStackTrace()
            }
    
            val showObserId = JSONArray().apply {
                if (!observerid.isNullOrEmpty()) {
                    observerid!!.split(",").forEach {
                        put(it)
                    }
                }
            }
    
            val showUserId = JSONArray().apply {
                if (!assignId.isNullOrEmpty()) {
                    assignId!!.split(",").forEach {
                        put(it)
                    }
                }
            }
    
            if (!Utils.isNetworkAvailable(this@AddTask)) {
                Toast.makeText(applicationContext, "Internet not available", Toast.LENGTH_LONG).show()
            } else {
                try {
                    val apiClient = RetroApi.client?.create(APIClient::class.java) ?: return
                    val postdata = JSONObject().apply {
                        put("TaskId", 0)
                        put("TaskLeadId", chooseLeadId)
                        put("TaskTitle", etTaskName!!.text.toString())
                        put("TaskDescription", Html.toHtml(etTaskDescription!!.text))
                        put("TaskCreatedBy", 0)
                        put("TaskAssignTo", showUserId)
                        put("TaskObserver", showObserId)
                        put("TaskStartDate", tvStartdate!!.text.toString())
                        put("TaskEndDate", tvEndDate!!.text.toString())
                        put("TaskCreatedDate", tvStartdate!!.text.toString())
                        put("TaskModifiedDate", tvStartdate!!.text.toString())
                        put("TaskStatus", 0)
                        put("IsTaskActive", activeValue)
                        put("IsDeleted", isDeleted)
                        put("TaskCompanyId", 0)
                        put("TaskPriority", leadPriorityId)
                    }
                    Log.d("request_edit_addtask", postdata.toString())
                    val requestBody =
                        postdata.toString().toRequestBody("application/json".toMediaTypeOrNull())
                    val call = apiClient.addUpdateTask(
                        "application/json",
                        sharedManager!!.sessionID,
                        requestBody
                    )
                    call.enqueue(object : Callback<JsonObject> {
                        override fun onResponse(
                            call: Call<JsonObject>,
                            response: Response<JsonObject>
                        ) {
                            customProgress?.hide()
                            if (response.isSuccessful) {
                                val responseBody = response.body()
                                Log.d(
                                    "addTaskApiResponseBody",
                                    responseBody?.toString() ?: "Empty response body"
                                )
                                if (responseBody != null) {
                                    processResponseAddTask()
                                } else {
                                    Log.e("Error", "Empty or null response body")
                                    runOnUiThread {
                                        Toast.makeText(
                                            this@AddTask,
                                            "Empty or null response body",
                                            Toast.LENGTH_SHORT
                                        ).show()
                                    }
                                }
                            } else {
                                val errorBody = response.errorBody()?.string()
                                Log.e("Error_Response", errorBody ?: "Empty error response body")
                                if (response.code() == 401) {
                                    Toast.makeText(
                                        this@AddTask,
                                        "Unauthorized request",
                                        Toast.LENGTH_SHORT
                                    ).show()
                                    LogOutApi(this@AddTask)
                                } else {
                                    runOnUiThread {
                                        Toast.makeText(
                                            this@AddTask,
                                            "Error: ${response.message()}",
                                            Toast.LENGTH_SHORT
                                        ).show()
                                    }
                                }
                            }
                        }
    
                        override fun onFailure(call: Call<JsonObject>, t: Throwable) {
                            customProgress?.hide()
                            t.printStackTrace()
                            Log.e("AddTaskError", "API call failed: ${t.message}")
                        }
                    })
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    
    Solution is -  
    
    @POST("/Api/AddUpdateTask")
        fun addUpdateTask(
            @Header("Content-Type") contentType: String?,
            @Header("SessionId") session: String?,
            @Body requestBody: RequestBody
        ): Call<Void>   //Change this 
    
    
and this part -
    
     call.enqueue(object : Callback<Void> {
                    override fun onResponse(call: Call<Void>, response: Response<Void>) {
                        customProgress?.hide()
                        if (response.isSuccessful) {
                            Log.d("SuccessfulResponse", "Response body: ${response.body()?.toString()}")
                            Log.d("SuccessfulResponse", "Response code: ${response.code()}")
                            processResponseAddTask()
                        } else {
                            val errorCode = response.code()
                            Log.e("AddTaskErrorResponse", "API call failed with error code: $errorCode")
                            val errorBody = response.errorBody()?.string()
                            Log.e("Error_Response", errorBody ?: "Empty error response body")
                            runOnUiThread {
                                Toast.makeText(
                                    this@AddTask,
                                    "Error: ${response.message()}",
                                    Toast.LENGTH_SHORT
                                ).show()
                            }
                        }
                    }

                    override fun onFailure(call: Call<Void>, t: Throwable) {
                        customProgress?.hide()
                        t.printStackTrace()
                        Log.e("AddTaskError", "API call failed: ${t.message}")
                    }
                })

for me its working fine.
© www.soinside.com 2019 - 2024. All rights reserved.