如何使用抽象对象保存和加载级别文件?

时间:2015-12-03 00:49:31

标签: java json serialization libgdx

我试图制作一个提供像马里奥制造商这样的保存功能的关卡编辑器 - 用户可以创建关卡并保存关卡数据。这通常是怎么做的?具体而言,我所挣扎的是我的等级包含一个敌人列表(一个抽象类)。当我写一个文件时,我可以编写具体敌人类的json表示,但是当我从文件中读取时,我需要知道它是什么具体类,以便将它重建到该特定类中。这看起来很痛苦 - 我必须手动添加一些代码来写出敌人保存时的类型类型,并添加代码以读取什么类类型并在读取时创建该类的实例。我害怕为我创造的每一个新敌人维持这一点。所以我的主要问题是如何才能最容易地将具体敌人列表读入抽象敌人列表?似乎在保存/加载时需要有关该类的一些知识。

另外,保存为JSON的方式还是更好的序列化?这有关系吗?

1 个答案:

答案 0 :(得分:0)

由于您将在程序启动时创建具体类,因此您需要知道每个类的实际类。有很多方法可以做到这一点。为了做一些简单的事情,你可以为每个具体类添加一个getLabel()方法,并将其用作开关来找出正确的具体类。

// Using jackson-databind
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readValue(json, JsonNode.class);

Enemy enemy = null;
if (GOOMBA_LABEL.equals(node.get("label").asText()))
   enemy = mapper.readValue(json, Goomba.class);

我非常喜欢使用JSON库功能将我的JSON解析为POJO。但是,执行上述操作实际上需要双重解析 - 1)解析为一些通用结构(如Map或JsonNode),检查标签然后2)解析为POJO。

你可以做的另一件事是在每个JSON字符串前加上一个“Magic Number”,让你知道它是哪种类型。然后你不必双重解析JSON。

DataInput input = new DataInputStream(fileInputStream);
int magic = input.readInt();

Enemy enemy = null;
if (GOOMBA_MAGIC == magic) {
   String json = input.readUTF();
   enemy = mapper.readValue(json, Goomba.class);
}

如果JSON是正确的序列化使用,那取决于你。关于它的好处是它是人类可读和可编辑的。如果性能或磁盘使用对您来说更重要,还有其他序列化技术。对于像这样的东西,JSON似乎很好。