gson OkHttpClient有时会得到不完整的json响应

vx6bjr1n  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(397)

我一直面临这个不完整的json错误,无法找到问题。API响应工作正常的POSTMAN。但这个问题发生在我的android模拟器,它只是随机发生。这个项目是用Kotlin匕首-剑柄retrofit 2 okhttp 3 gson构建的。
成功响应

I/okhttp.OkHttpClient: <-- 200 OK http://10.0.2.2:8000/api/v1/user/friend/mutual?name=as (217ms)
I/okhttp.OkHttpClient: Host: 10.0.2.2:8000
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:38:59 GMT
I/okhttp.OkHttpClient: Connection: close
I/okhttp.OkHttpClient: X-Powered-By: PHP/7.4.13
I/okhttp.OkHttpClient: Cache-Control: no-cache, private
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:38:59 GMT
I/okhttp.OkHttpClient: Content-Type: application/json
I/okhttp.OkHttpClient: X-RateLimit-Limit: 60
I/okhttp.OkHttpClient: X-RateLimit-Remaining: 52
I/okhttp.OkHttpClient: Access-Control-Allow-Origin: *
I/okhttp.OkHttpClient: {"friends":[{"user_id":16,"name":"Grant Erdman","username":"lilla.kulas","email":"claudie04@example.org","image":"https:\/\/via.placeholder.com\/640x480.png\/00dd44?text=dolor","relationship":"friend"}],"requests":[]}
I/okhttp.OkHttpClient: <-- END HTTP (217-byte body)

不完整的Json响应缺少“}”

I/okhttp.OkHttpClient: <-- 200 OK http://10.0.2.2:8000/api/v1/user/friend/mutual?name=as (198ms)
I/okhttp.OkHttpClient: Host: 10.0.2.2:8000
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:39:00 GMT
I/okhttp.OkHttpClient: Connection: close
I/okhttp.OkHttpClient: X-Powered-By: PHP/7.4.13
I/okhttp.OkHttpClient: Cache-Control: no-cache, private
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:39:00 GMT
I/okhttp.OkHttpClient: Content-Type: application/json
I/okhttp.OkHttpClient: X-RateLimit-Limit: 60
I/okhttp.OkHttpClient: X-RateLimit-Remaining: 51
I/okhttp.OkHttpClient: Access-Control-Allow-Origin: *
I/okhttp.OkHttpClient: {"friends":[{"user_id":16,"name":"Grant Erdman","username":"lilla.kulas","email":"claudie04@example.org","image":"https:\/\/via.placeholder.com\/640x480.png\/00dd44?text=dolor","relationship":"friend"}],"requests":[]
I/okhttp.OkHttpClient: <-- END HTTP (216-byte body)
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.findplan, PID: 4695
    java.io.EOFException: End of input at line 1 column 217 path $.requests
        at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1395)
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:481)
        at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:413)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
        at com.example.findplan.utils.NullOnEmptyConverterFactory$1.convert(NullOnEmptyConverterFactory.java:20)
        at com.example.findplan.utils.NullOnEmptyConverterFactory$1.convert(NullOnEmptyConverterFactory.java:16)
        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
        at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
I/Process: Sending signal. PID: 4695 SIG: 9

我的网络模块

@Singleton
    @Provides
    fun provideOkHttpClient(mySharedPreferences: MySharedPreferences): OkHttpClient {
        val builder = OkHttpClient
            .Builder()
            .connectTimeout(1, TimeUnit.MINUTES)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
        val authenticationInterceptor = AuthenticationInterceptor(mySharedPreferences)
        builder.addInterceptor(authenticationInterceptor)
        val interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addNetworkInterceptor(interceptor)

        return builder.build()
    }

    @Singleton
    @Provides
    fun provideGson(): Gson {
        return GsonBuilder()
            .setLenient()
            .create()
    }

    @Singleton
    @Provides
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(NullOnEmptyConverterFactory())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

空时为空转换器工厂

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);
            }
        };
    }
}
js4nwp54

js4nwp541#

我怀疑Android模拟器可能会干扰你这里。我已经看到它的问题,特别是在Windows上的行为不当。
https://issuetracker.google.com/issues/119027639
如果你想解决这个问题,可以考虑改变你的服务器,使用Connection: close以外的东西来终止你的响应正文,比如分块编码或者内容长度头。

相关问题