使用 Gson 序列化和反序列化 org.bukkit.ItemStack
使用 序列化 org Gson Bukkit
2023-06-13 09:14:05 时间
本文最后更新于 451 天前,其中的信息可能已经有所发展或是发生改变。
使用 Gson 序列化和反序列化 org.bukkit.ItemStack
写这玩意的原因
昨天肝了一整天 这个插件,为了方便起见我希望使用 Json 来存储 ItemStack 信息,结果没想到为了序列化这个 ItemStack 花了我一整个下午的时间。在 StackOverFlow 和 SpigotMC 兜兜转转一大圈后,终于写出来了序列化代码。
正好刚刚逛论坛的时候,看到了同小组的 这个教程,心想正好他只写了 YAML,没有写 GSON,我就帮忙给他补充一下了233。
开始
探寻 ItemStack 序列化的实质
既然 Bukkit API 已经向我们提供了 ItemStack 的序列化和反序列化方法,那么就让我们深入一下这两个方法:
// on ItemStack.class
@Utility
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("type", getType().name());
if (getDurability() != 0) {
result.put("damage", getDurability());
}
if (getAmount() != 1) {
result.put("amount", getAmount());
}
ItemMeta meta = getItemMeta();
if (!Bukkit.getItemFactory().equals(meta, null)) {
result.put("meta", meta);
}
return result;
}
// on ItemStack.class
public static ItemStack deserialize(Map<String, Object> args) {
Material type = Material.getMaterial((String) args.get("type"));
short damage = 0;
int amount = 1;
if (args.containsKey("damage")) {
damage = ((Number) args.get("damage")).shortValue();
}
if (args.containsKey("amount")) {
amount = ((Number) args.get("amount")).intValue();
}
ItemStack result = new ItemStack(type, amount, damage);
if (args.containsKey("enchantments")) { // Backward compatiblity, @deprecated
Object raw = args.get("enchantments");
if (raw instanceof Map) {
Map<?, ?> map = (Map<?, ?>) raw;
for (Map.Entry<?, ?> entry : map.entrySet()) {
Enchantment enchantment = Enchantment.getByName(entry.getKey().toString());
if ((enchantment != null) && (entry.getValue() instanceof Integer)) {
result.addUnsafeEnchantment(enchantment, (Integer) entry.getValue());
}
}
}
} else if (args.containsKey("meta")) { // We cannot and will not have meta when enchantments (pre-ItemMeta) exist
Object raw = args.get("meta");
if (raw instanceof ItemMeta) {
result.setItemMeta((ItemMeta) raw);
}
}
return result;
}
由此看来,就非常明了了:原来 ItemStack 的序列化就是将各种属性存储到一个 Map<String, Object>
里,那么我们只需要将这个 Map<String,Object>
通过 Gson 序列化为 Json,就解决问题啦!
配置 Gson 并自定义 Gson 序列化器
默认情况下,Gson 并不会调用 ItemStack 的序列化和反序列化方法,如果不调用这些方法而强行序列化,就会引发奇怪的报错。因此我们需要自定义 Gson 序列化器。因此,创建 ItemStackSerializer
,并实现 JsonDeserializer<ItemStack>, JsonSerializer<ItemStack>
:
public class ItemStackSerializer implements JsonDeserializer<ItemStack>, JsonSerializer<ItemStack> {
@Override
public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return ItemStack.deserialize(GsonBuilder().create().fromJson(json, new TypeToken<Map<String, Object>>() {}.getType()));
}
@Override
public JsonElement serialize(ItemStack src, Type typeOfSrc, JsonSerializationContext context) {
return new GsonBuilder().create().toJsonTree(src.getItem().serialize());
}
}
然后,使用 GsonBuilder 生成一个注册了 ItemStack 序列化器的 Gson 对象:
Gson gson = new GsonBuilder()
.enableComplexMapKeySerialization()
.serializeNulls()
.setPrettyPrinting()
.registerTypeAdapter(ItemStack.class, new ItemStackSerializer())
.create();
这样一来,我们就可以使用 gson.fromJson
或是 gson.toJson
将 ItemStack 正确的序列化或是反序列化啦!
相关文章
- reaver 使用方法和技巧
- xshell连接虚拟机使用的是什么连接模式_虚拟机安装ssh服务
- 使用SpringFramework+Restlet实现rest服务
- msfconsole 控制台使用和操作[通俗易懂]
- 使用pickle进行序列化和反序列化
- 在微信小程序上做一个「博客园年度总结」:使用redis存储数据
- 使用 Chrome 开发者工具分析 SAP UI5 应用的 JavaScript 代码执行性能瓶颈
- 【Android Protobuf 序列化】Protobuf 使用 ( protoc 编译器简介 | 下载 protoc 编译器 | 使用 protoc 编译器编译 .proto 源文件 )
- 【Android Protobuf 序列化】Protobuf 使用 ( protobuf-gradle-plugin 插件简介 | Android Studio 中配置插件 | AS 中编译源文件 )
- 【Groovy】json 序列化 ( 类对象转为 json 字符串 | 使用 JsonBuilder 进行转换 | 使用 JsonOutput 进行转换 | 将 json 字符串格式化输出 )
- 【Groovy】xml 序列化 ( 使用 StreamingMarkupBuilder 生成 xml 数据 | mkp.xmlDeclaration() 生成 xml 版本数据 )
- 【Groovy】Xml 反序列化 ( 使用 XmlParser 解析 Xml 文件 | 删除 Xml 文件中的节点 | 增加 Xml 文件中的节点 | 将修改后的 Xml 数据输出到文件中 )
- Django REST Framework-序列化器的使用(一)
- 探索Linux使用:指南与实践(findlinux用法)
- Oracle 视图 ALL_MVIEW_DETAIL_RELATIONS 官方解释,作用,如何使用详细说明
- 检索使用Linux C实现中文检索功能(linuxc汉字)
- 如何在 Python Web 框架 Django 中使用序列化器
- Linux下使用编辑文件命令,畅快书写你的代码(linux编辑文件命令)
- 化使用MSSQL系统表实现数据序列化(mssql系统表 序列)
- 使用MySQL解析XML大于号元素(mysql xml大于号)
- Oracle加大对国密算法支持力度(Oracle使用国密算法)
- Redis使用序列化提取值(redis获取值序列化)
- PHP数组操作汇总php数组的使用技巧
- 使用XmlSerializer序列化List对象成XML格式(list对象序列化)
- C#特性匿名类型与隐式类型局部变量使用介绍
- JavaScript中使用stopPropagation函数停止事件传播例子