我使用 Retrofit 2 作为我制作的 API,并使用 Retrofit Gson 将 API 响应转换为对象。我有一个包含 JSON 模型的包(作为一个类),我需要 Gson 来访问这些模型。
当我添加行来打开 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 [email protected]/retrofit2.Utils.methodError(Utils.java:56)
at [email protected]/retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:139)
at [email protected]/retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:97)
at [email protected]/retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
at [email protected]/retrofit2.Retrofit.loadServiceMethod(Retrofit.java:235)
at [email protected]/retrofit2.Retrofit$1.invoke(Retrofit.java:177)
at jdk.proxy2/com.sun.proxy.jdk.proxy2.$Proxy6.login(Unknown Source)
at [email protected]/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 [email protected]/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38)
at [email protected]/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286)
at [email protected]/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 [email protected]/com.google.gson.Gson.getAdapter(Gson.java:556)
at [email protected]/retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:64)
at [email protected]/retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:418)
at [email protected]/retrofit2.Retrofit.responseBodyConverter(Retrofit.java:401)
at [email protected]/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 [email protected]/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:35)
... 19 more
这是我的模块-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;
}
我在GitHub上推送了项目,这是链接
根异常中已经提供了解决方案(强调我的):
原因:java.lang.reflect.InaccessibleObjectException:无法 将字段设置为 private Final java.lang.String fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get.LoginResponse.message 可访问:模块 fr.plaglefleau.banksystemdesktop 无法“打开” fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get”到 模块 com.google.gson
换句话说,您需要修改您的
module-info.java
并添加以下 opens
语句。
opens fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get
to com.google.gson;
[..]我在上层包装上打开它
正如 Holger 的评论中已经提到的,虽然 Java 中包的命名是(或者,似乎是)分层的,但包不是;每个包名都定义了自己独立的命名空间。
换句话说,打开包装
fr.plaglefleau.banksystemdesktop
并不会同时打开包装fr.plaglefleau.banksystemdesktop.api.models.bankapi.response.get
。就 Java 而言,它们是两个不同且独立的实体(即后者不嵌套在前者中)。
关于更新后看到的
Package ... not found in module
错误module-info.java
:您可以通过以下任一方法解决此问题:
build.gradle
以便 compileJava
任务可以看到 Kotlin 类,请参阅 Kotlin 文档module-info.java
并删除 opens ... to ...;
并改为写入 open module
:
open module fr.plaglefleau.banksystemdesktop {
requires ...
}
另请参阅了解 Java 9 模块。然而,当 Gson 或其他库意外地使用了您实际上并不想要打开的某个包中的类的反射时,这可能会使故障排除变得更加困难。请注意,Gson 主要是为 Java 设计的。它可能适用于某些 Kotlin 功能,但不适用于所有功能(例如,不考虑可空性)。由于您的模型类是用 Kotlin 编写的,因此最好使用具有明确 Kotlin 支持的 JSON 库,例如 https://github.com/square/moshi 和 相应的 Retrofit 转换器。