序列化
simbot通过 kotlinx-serialization 完成标准序列化。
kotlinx-serialization
无关数据结构,你可以通过其将消息序列化为任何 支持的
结果。本章节内我们会以 JSON
为例。
标准消息
首先,如果需要使用 kotlinx-serialization
,首先你要确定需要序列化对象的范围。毕竟消息对象接口 Message.Element
无法预知所有其实现类,
因此所有组件在提供消息实现的同时,也需要提供其对应的多态序列化信息,也就是 SerializersModule
。
在simbot中提供的标准消息实现可以通过 Messages.serializersModule
获取。
- Kotlin
- Java
val module = Messages.serializersModule
SerializersModule module = Messages.getSerializersModule();
当你想要序列化一个仅包含了标准消息的消息链,那么就可以直接使用了。
- Kotlin
- Java
val json = Json {
// 指定序列化信息
serializersModule = Messages.serializersModule
// config...
isLenient = true
}
// 仅包含标准消息的消息链
val messages: Messages = "你好".toText() + AtAll + Face(123.ID)
val jsonStr = json.encodeToString(Messages.serializer, messages)
在Java中,想要构建一个 kotlinx.serialization.json.Json
会相对比较困难。simbot内提供了一个简易的工具 MessageSerializationUtil
来辅助Java开发者来处理序列化的情况。
MessagesBuilder builder = new MessagesBuilder();
// 构建一个Json序列化器, 并配置序列化信息和Json自身的配置
Json json = MessageSerializationUtil.createJson(null, (config) -> {
// isLenient = true
config.setLenient(true);
// config...
}, Messages.getSerializersModule());
// 仅包含标准消息的消息链
Messages messages = builder.text("你好").atAll().face(Identifies.ID(123)).build();
String jsonStr = json.encodeToString(Messages.getSerializer(), messages);
上述示例的序列化结果如下:
[{"type":"m.std.text","text":"你好"},{"type":"m.std.atAll"},{"type":"m.std.face","id":"123"}]
反之亦然。反序列化也通过 kotlinx-serialization
完成。
- Kotlin
- Java
val json = Json {
// config...
isLenient = true
// 记得指定序列化信息
serializersModule = Messages.serializersModule
}
val jsonStr = """[{"type":"m.std.text","text":"你好"},{"type":"m.std.atAll"},{"type":"m.std.face","id":"123"}]"""
val messages = json.decodeFromString(Messages.serializer, jsonStr)
在Java中,想要构建一个 kotlinx.serialization.json.Json
会相对比较困难。simbot内提供了一个简易的工具 MessageSerializationUtil
来辅助Java开发者来处理序列化的情况。
String jsonStr = "[{\"type\":\"m.std.text\",\"text\":\"你好\"},{\"type\":\"m.std.atAll\"},{\"type\":\"m.std.face\",\"id\":\"123\"}]";
// 构建一个Json序列化器, 并配置序列化信息和Json自身的配置
Json json = MessageSerializationUtil.createJson(null, (config) -> {
// isLenient = true
config.setLenient(true);
// config...
}, Messages.getSerializersModule());
Messages messages = json.decodeFromString(Messages.getSerializer(), jsonStr);
你可能注意到了,在进行序列化或反序列化时,总会使用 Messages.serializer
并将结果序列化为一个列表(如JsonArray)。
Messages.serializer
为 Messages
的序列化实现,它会将 Messages
视为一个 Message.Element
的集合来看待。
组件消息
每个组件基本上都会有它们自己专属的消息类型实现,因此当你的程序包含一个或多个组件中时,只使用标准消息的序列化信息 Messages.serializersModule
是不够的。
绝大多数情况下,一个组件会提供其专属的消息序列化信息,并且 Component
类型也要求其实现类必须提供 componentSerializersModule
属性。
由simbot所提供的组件中,消息序列化信息会通过 Component
的实现以及静态属性等多个方式对外提供。举个例子:
- Kotlin
- Java
val serializersModule = SerializersModule {
include(Messages.serializersModule)
// Kook组件的序列化信息
include(KookComponent.messageSerializersModule)
// Mirai组件的序列化信息
include(MiraiComponent.messageSerializersModule)
}
val json = Json {
this.serializersModule = serializersModule
}
// 合并标准消息的序列化信息 和 Kook组件的序列化信息
SerializersModule module = SerializersModuleKt.plus(Messages.getSerializersModule(), KookComponent.getMessageSerializersModule());
// 再合并进Mirai组件的序列化信息
module = SerializersModuleKt.plus(module, MiraiComponent.getMessageSerializersModule());
// 构建一个Json序列化器, 并配置序列化信息和Json自身的配置
Json json = MessageSerializationUtil.createJson(null, (config) -> {
// config...
}, module);
// 构建一个Json序列化器, 并配置序列化信息和Json自身的配置
Json json = MessageSerializationUtil.createJson(null, (config) -> {
// config...
},
Messages.getSerializersModule(), // 标准消息的序列化信息
KookComponent.getMessageSerializersModule(), // Kook组件的序列化信息
MiraiComponent.getMessageSerializersModule() // Mirai组件的序列化信息
);
除了这种提前定义好的方式以外,也可以在 Application
启动后来动态获取所有已加载组件中的序列化信息。
- Kotlin
- Java
val application = createSimbotApplication(...) {
// ...
}
// 遍历所有组件
for (component in application.environment.components) {
// 此组件的序列化信息
val componentSerializersModule = component.componentSerializersModule
}
Application application = Applications.createSimbotApplication(..., null, (b, c) -> {
// ...
});
List<Component> components = application.getEnvironment().getComponents();
// 遍历所有组件
for (Component component : components) {
// 此组件的序列化信息
SerializersModule componentSerializersModule = component.getComponentSerializersModule();
}