提问人:Felix 提问时间:10/30/2023 更新时间:11/17/2023 访问量:76
GSON JSON 序列化 - 无法使字段私有 int java.sql.Timestamp.nanos 可访问
GSON JSON serialization - Unable to make field private int java.sql.Timestamp.nanos accessible
问:
自从最近的 Java 升级以来,我们无法序列化从 SQL 数据库读取的对象,其值映射到 .底层数据库是 SAP Sybase,我们的客户能够通过像 这样简单的查询来重现该问题。java.sql.Timestamp
Select getdate()
环境:Java 17.0.4.1、Eclipse Adoptium、Mac OS X 14.0
这不是我们添加或类似选项的选项。我还尝试调试到 Gson 库中,发现该对象使用了“反射适配器”。add-opens=java.sql=ALL-UNNAMED
TypeAdapterRuntimeTypeWrapper
java.sql.Timestamp
作为一种解决方法,我现在使用 Jackson 库作为后备,它能够毫无问题地序列化我的对象(即下面代码中的第二个 try 子句可以正常工作):
try {
json = GSON.toJson(object);
} catch (Exception e) {
log.warn("Failed to serialize JSON. Trying alternative serializer (1).", e);
try {
json = new ObjectMapper().writeValueAsString(object);
} catch (Exception e1) {
log.warn("Failed to serialize JSON. Leaving null.", e);
}
}
堆栈跟踪:
com.google.gson.JsonIOException: Failed making field 'java.sql.Timestamp#nanos' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.
at com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)
at com.google.gson.Gson.getAdapter(Gson.java:556)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:207)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:144)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:207)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:144)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:207)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:144)
at com.google.gson.Gson.toJson(Gson.java:842)
at com.google.gson.Gson.toJson(Gson.java:812)
at com.google.gson.Gson.toJson(Gson.java:759)
at com.google.gson.Gson.toJson(Gson.java:736)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private int java.sql.Timestamp.nanos accessible: module java.sql does not "opens java.sql" to unnamed module @2554782d
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Field.setAccessible(Unknown Source)
at com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:35)
有什么想法吗?
答:
0赞
mariusi
11/17/2023
#1
看来你必须编写自己的TypeAdapter。或者为失败的特定类型添加排除项。在故障排除指南中发现:https://github.com/google/gson/blob/main/Troubleshooting.md#-inaccessibleobjectexception-module--does-not-opens--to-unnamed-module 有确切的错误,您的解决方法看起来也很好。
评论
JavaFX
module-info.java
java.sql.Timestamp
适配器,但也许 Gson 中的逻辑有缺陷并且由于某种原因没有应用?您能否调试并检查内部 Gson 类的行为方式?但是,Gson 的内置适配器使用的格式可能不是必需的,因此您可能需要编写自定义适配器。SqlTypesSupport