各位除非是自动序列化的,或多或少应该都是用 Bukkit 自带的
但是,有一天,我遇上了要读取下面这个玩意的需求
以防脑子一时没转过弯来,提醒一下,这是一个列表 (
但是 Bukkit 只给了一个
如果你要用这玩意,恭喜你,你要写额外空检查、类型检查等等一大堆乱七八糟的玩意,ConfigurationSection 提供的便利全都没有啦。
这只是配置相对简单的场景,要是列表下套的配置还有子项,比如
甚至于还有可能列表套配置再套列表,那就非常麻烦了…
我的解决方法是想办法把它返回的这个
这样读取起来就会相对舒适一点了。
YamlConfiguration
来读写 yml 配置的,一般如无必要都是直接使用内置的来得快一些。但是,有一天,我遇上了要读取下面这个玩意的需求
YAML:
rewards:
- type: mythic
mythic: ExampleItem
rate: 0.05
amount: 1
- type: vanilla
material: DIAMOND
rate: 0.1
amount: 1
- type: vanilla
material: IRON_INGOT
rate: 0.5
amount: 1
List
),列表里面套配置 (ConfigurationSection
)。但是 Bukkit 只给了一个
getMapList
用来读取这种格式,返回的是 List<Map<?, ?>>
。如果你要用这玩意,恭喜你,你要写额外空检查、类型检查等等一大堆乱七八糟的玩意,ConfigurationSection 提供的便利全都没有啦。
Java:
for (Map<?, ?> map : config.getMapList("rewards")) {
String type = (String) map.get("type");
Object amountRaw = map.get("amount"); // 看着就烦
int amount = amountRaw instance Integer ? (int) amountRaw : 1;
// ...
}
这只是配置相对简单的场景,要是列表下套的配置还有子项,比如
YAML:
rewards:
- type: mythic
mythic:
type: ExampleItem
level: 10
甚至于还有可能列表套配置再套列表,那就非常麻烦了…
我的解决方法是想办法把它返回的这个
List<Map<?, ?>>
给转换成 List<ConfigurationSection>
,下面是实现代码,唯一的缺点是保存会丢注释,如果这个配置只读不写,那问题不大。
Java:
@NotNull
public static List<ConfigurationSection> getSectionList(ConfigurationSection parent, String key) {
List<ConfigurationSection> list = new ArrayList<>();
List<Map<?, ?>> rawList = parent.getMapList(key);
for (Map<?, ?> map : rawList) {
MemoryConfiguration section = new MemoryConfiguration();
for (Map.Entry<?, ?> entry : map.entrySet()) {
String sectionKey = entry.getKey().toString();
section.set(sectionKey, processValue(section, sectionKey, entry.getValue()));
}
list.add(section);
}
return list;
}
private static Object processValue(ConfigurationSection parent, String key, Object value) {
if (value instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) value;
ConfigurationSection section;
if (parent == null || key == null) { // 兼容 List
section = new MemoryConfiguration();
} else { // 兼容 Map
section = parent.createSection(key);
}
for (Map.Entry<?, ?> entry : map.entrySet()) {
String mapKey = entry.getKey().toString();
section.set(mapKey, processValue(section, mapKey, entry.getValue()));
}
return section;
}
if (value instanceof List<?>) {
List<?> list = (List<?>) value;
List<Object> result = new ArrayList<>();
for (Object object : list) {
result.add(processValue(null, null, object));
}
return result;
}
return value;
}
这样读取起来就会相对舒适一点了。
Java:
for (ConfigurationSection section : getSectionList(config, "rewards")) {
String type = section.getString("type");
int amount = section.getInt("amount", 1);
// ...
}
本文代码来自我的仓库 PluginBase
与仓库共用许可证 MIT License