Java模块包访问异常:Retrofit Gson转换JSON模型失败
问题描述
使用Retrofit 2对接自研API,通过Retrofit Gson将API响应转换为实体对象。存放JSON模型类的包需要Gson访问,但添加开放该包的配置时构建报错;开放上级被javafx.fxml正常访问的包后构建没问题,但运行时Gson抛出如下错误:
Exception in thread "DefaultDispatcher-worker-2" java.lang.IllegalArgumentException: Unable to create converter for class fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse for method BankApi.login at retrofit2@2.11.0/retrofit2.Utils.methodError(Utils.java:56) at retrofit2@2.11.0/retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:139) at retrofit2@2.11.0/retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:97) at retrofit2@2.11.0/retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39) at retrofit2@2.11.0/retrofit2.Retrofit.loadServiceMethod(Retrofit.java:235) at retrofit2@2.11.0/retrofit2.Retrofit$1.invoke(Retrofit.java:177) at jdk.proxy2/com.sun.proxy.jdk.proxy2.$Proxy6.login(Unknown Source) at fr.plaglefleau.banksystemdesktop@1.0-SNAPSHOT/fr.plaglefleau.banksystemdesktop.SignInController$signIn$1.invokeSuspend(SignInController.kt:95) at kotlin.stdlib/kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.core/kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at kotlinx.coroutines.core/kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:589) at kotlinx.coroutines.core/kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:806) at kotlinx.coroutines.core/kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:710) at kotlinx.coroutines.core/kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:697) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@5216989, Dispatchers.Default] Caused by: com.google.gson.JsonIOException: Failed making field 'fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse#message' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type. at com.google.gson@2.10.1/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38) at com.google.gson@2.10.1/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286) at com.google.gson@2.10.1/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130) Caused by: com.google.gson.JsonIOException: Failed making field 'fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse#message' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type. at com.google.gson@2.10.1/com.google.gson.Gson.getAdapter(Gson.java:556) at retrofit2.converter.gson@2.11.0/retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:64) at retrofit2@2.11.0/retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:418) at retrofit2@2.11.0/retrofit2.Retrofit.responseBodyConverter(Retrofit.java:401) at retrofit2@2.11.0/retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:137) ... 12 more Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.lang.String fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse.message accessible: module fr.plaglefleau.banksystemdesktop does not "opens fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get" to module com.google.gson at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.lang.String fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse.message accessible: module fr.plaglefleau.banksystemdesktop does not "opens fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get" to module com.google.gson at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178) at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) at com.google.gson@2.10.1/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:35) ... 19 more
当前module-info.java代码:
module fr.plaglefleau.banksystemdesktop { requires javafx.controls; requires javafx.fxml; requires kotlin.stdlib; requires TranslationLibrary.main; requires kotlinx.coroutines.core; requires org.jetbrains.annotations; requires retrofit2; requires retrofit2.converter.gson; requires com.google.gson; opens fr.plaglefleau.banksystemdesktop to javafx.fxml, retrofit2.converter.gson; exports fr.plaglefleau.banksystemdesktop; }
解决方案
错误根源是Java模块系统未向com.google.gson开放实体类所在的具体子包。你当前仅开放了根包fr.plaglefleau.banksystemdesktop,但Gson需要访问的是fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get下的LoginResponse类,必须明确开放该包。
修改module-info.java,添加对应包的开放声明:
module fr.plaglefleau.banksystemdesktop { requires javafx.controls; requires javafx.fxml; requires kotlin.stdlib; requires TranslationLibrary.main; requires kotlinx.coroutines.core; requires org.jetbrains.annotations; requires retrofit2; requires retrofit2.converter.gson; requires com.google.gson; opens fr.plaglefleau.banksystemdesktop to javafx.fxml, retrofit2.converter.gson; // 开放LoginResponse所在的包给Gson opens fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get to com.google.gson; // 若有其他实体类子包,同理添加开放声明 // opens fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.post to com.google.gson; exports fr.plaglefleau.banksystemdesktop; }
如果所有实体类都集中在api.models父包下,也可以一次性开放整个父包,简化配置:
opens fr.plaglefleau.banksystemdesktop.api.models to com.google.gson;
这样Gson就能通过反射访问实体类的私有字段,完成JSON与实体对象的转换。
内容的提问来源于stack exchange,提问作者PlagLeFleau
相关产品推荐
相关产品推荐

