我正在用Java Swing制作一个游戏,其中有一个很大的POJO,用于存储游戏的运行时数据,如精灵位置、当前显示的效果等。我希望能够将其作为JSON保存到一个文件中,然后再从一个文件中重建它。我发现Gson应该就是这样做的。但到目前为止,我还没有设法让它工作。我总是遇到这样的问题:它无法使嵌套在存储类中的某些变量可访问。
以下是我目前如何使用Gson:
public void loadGameState(String path) throws FileNotFoundException {
gameStateData = gson.fromJson(new FileReader(path), gameStateData.getClass());
}
public void writeGameState(String path) throws IOException {
gson.toJson(gameStateData, new FileWriter(path));
}
以下是我在尝试使用writeGameState
时收到的错误消息:
Exception in thread "AWT-EventQueue-0" com.google.gson.JsonIOException: Failed making field 'java.util.Random#seed' accessible; either change its visibility or write a custom TypeAdapter for its declaring type
at com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:22)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:158)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:101)
at com.google.gson.Gson.getAdapter(Gson.java:501)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:116)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:165)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:101)
at com.google.gson.Gson.getAdapter(Gson.java:501)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:116)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:165)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:101)
at com.google.gson.Gson.getAdapter(Gson.java:501)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
at com.google.gson.Gson.getAdapter(Gson.java:501)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:116)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:165)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:101)
at com.google.gson.Gson.getAdapter(Gson.java:501)
at com.google.gson.Gson.toJson(Gson.java:739)
at com.google.gson.Gson.toJson(Gson.java:726)
at com.google.gson.Gson.toJson(Gson.java:701)
at gamestatedata.GameStateManager.writeGameState(GameStateManager.java:27)
at rendering.MainWindow.actionPerformed(MainWindow.java:205)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6626)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389)
at java.desktop/java.awt.Component.processEvent(Component.java:6391)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:746)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:744)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.concurrent.atomic.AtomicLong java.util.Random.seed accessible: module java.base does not "opens java.util" to unnamed module @55129b54
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
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.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:19)
... 57 more
GameStateData
是我一开始提到的大POJO,它大约有300行,包含30个变量和它们的getter,所以我不确定粘贴是否有帮助。我的POJO中的所有字段都是私有的,但我尝试将它们全部设置为protected或public,但没有帮助,因为有些字段也包含私有或protected字段,所以仍然会出现同样的问题。
我正在使用java 17.0.0和Gson 2.9.0以及Maven。我想我正在使用Maven来导入Gson,但老实说,我对它是如何工作的有点困惑,但这里是我的pom.xml,只是为了确保:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hu.elte.inf</groupId>
<artifactId>ThesisMVN</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
据我所知,这个问题可以通过将Gson移到类路径中来解决,但是我已经这样做了,但是仍然遇到了这个问题。有没有关于如何确保它正常工作的分步指南?有没有其他工具仍然可以让我毫不费力地从Java对象读取和写入JSON?
问题出在我的POJO上,我对收到的错误信息轻描淡写,对序列化和transient关键字缺乏了解。我的POJO有几个图像,应该都是暂时的,我的问题的另一个来源是一个无法正确访问的随机示例。TLDR:请使用transient
关键字并注意错误消息。
1条答案
按热度按时间fbcarpbf1#
您的POJO可以只实现
Serializable
接口,然后您可以轻松地在具有文件流的文件中写入该类或从中读取该类。You can find more about it here