Merlin (梅林) 是一个用于 protobuf message 和 java bean 转换的工具
<dependency>
<groupId>cn.org.merlin</groupId>
<artifactId>message-convert</artifactId>
<version>1.0.0</version>
</dependency>
// create instance
Merlin merlin = Merlin.newBuilder().build();
// object to message
ConvertTestMessage result =
merlin.objectToMessage(bean, ConvertTestMessage.getDefaultInstance());
// message to object
ConvertTestBean result = merlin.messageToObject(message, ConvertTestBean.class);
# | protoType | javaType | remark |
---|---|---|---|
1 | int32 | int | basic |
2 | int32 | char | basic |
3 | int32 | byte | basic |
4 | int32 | short | basic |
5 | int64 | long | basic |
6 | float | float | basic |
7 | double | double | basic |
8 | boolean | boolean | basic |
9 | string | string | basic |
10 | bytes | byte[] | basic |
11 | enum | enum | enum |
12 | message | bean | bean |
13 | int64 | Date | special |
14 | map | map | container |
15 | repeated | array | container |
16 | repeated | list | container |
17 | repeated | set | container |
对于所有非 message 的类型, 支持在 proto 中使用 message 进行一层包装 , 包装后的结构可以正常转换
例如: String 和 Message 转换
message StringWrap{
string value = 1;
}
Integer , Long 等包装类, 需要对 null 进行区分时, 可以使用 wrap 能力包装 (pb 的基本类型没有 null) google 官方也直接提供了对应包装型 message (com.google.Int32Value , com.google.Int64Value 等) , 可以直接使用
class Bean{
Integer id;
}
syntax = "proto3";
option java_package = "com.merlin";
import "google/protobuf/wrappers.proto";
message BeanMessage {
com.google.Int32Value id = 1;
}
不需要对 null 进行区分时, 则直接使用基本类型 (int32 ,int64 等)
可以使用 wrap 能力对每层的结构进行包装, 例如 Map<String, List > 对应的 message :
message StringMultimap {
map<string, StringList> values = 1;
}
message StringList {
repeated string values = 1;
}
实现 MessageConverter 接口, 自定义 message -> bean 的转换规则, 注册后适用于整个 merlin 实例 , 支持直接调用方法注册和 SPI 注册
UserConverter userConverter = new UserConverter();
ArrayList<MessageConverter> converters = Lists.newArrayList(userConverter);
Merlin merlin = Merlin.newBuilder().withConverters(converters).build();
SPI示例 在 resources 下创建 META-INF/services/MessageConverter 文件, 文件内一行一个填入实现的转换器
实现 TypeAdaptor 接口, 自定义 field -> bean 的转换规则, 注册后适用于整个 merlin 实例 , 支持直接调用方法注册和 SPI 注册, 示例:
# | protoType | fieldType |
---|---|---|
1 | int32,sint32,sfixed32 | INT32 |
2 | uint32,fixed32 | UINT32 |
3 | int64,sint64,sfixed64 | INT64 |
4 | uint64,fixed64 | UINT64 |
5 | float | FLOAT |
6 | double | DOUBLE |
7 | boolean | BOOLEAN |
8 | string | STRING |
9 | bytes | BYTE_STRING |
UserConverter userConverter = new UserConverter();
ArrayList<MessageConverter> converters = Lists.newArrayList(userConverter);
Merlin merlin = Merlin.newBuilder().withConverters(converters).build();
SPI示例 在 resources 下创建 META-INF/services/MessageConverter 文件, 文件内一行一个填入实现的属性转换
示例:
merlin 提供了全局别名控制器和 protobuf_field_option 别名能力 protobuf(注意要 import merlin 的 descriptor):
syntax = "proto3";
option java_package = "cn.org.merlin";
option java_multiple_files = true;
import "merlin/Descriptor.proto";
message AliasTestMessage1 {
string id = 1 [(field_alias) = "userID"];
string name = 2 [(field_alias) = "userName"];
}
全局控制:
Merlin merlin = Merlin.newBuilder().withAliasController(new AliasManger()).build();
SPI示例 在 resources 下创建 META-INF/services/AliasController 文件, 只支持一个
如果 javabean 中用了父类或者抽象类 , message 中需要定义对应的 oneof 字段