Java 中的通用 protobuf 反序列化器
generic protobuf deserializer in Java
我正在尝试编写一个通用的 java class 可用于 deserialize/parse 任何 protobuf 消息。
代码在完美世界中应该是这样的:
public abstract class ProtoDeserializer<T extends Message> {
public T deserialize(final byte[] bytes) throws Exception {
Parser<T> parser = T.getParserForType(); // Syntax Error: this method is not static!
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
但是,我无法获得通用 protobuf 消息的正确解析器。实现这种通用 class 的正确方法是什么?
最简单的是将解析器作为参数传递给构造函数:
public abstract class ProtoDeserializer<T extends Message> {
private final Parser<T> parser;
public ProtoDeserializer(Parser<T> parser) {
this.parser = parser;
}
public T deserialize(final byte[] bytes) throws Exception {
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
Passing the parser is my current workaround. But it would be nice to avoid it, because it's redundant information.
对你来说可能是多余的,但对compiler/runtime来说并不多余。
如果您认为可以创建 class 的原始实现:
ProtoDeserializer proto = new ProtoDeserializer() {
...
};
类型 T
必须来自 某个地方 。
这只是被擦除泛型的现实。如果您需要泛型参数的类型信息,则必须手动提供。
您可以尝试的另一个 hack 是从实现子 class:
中获取具体类型参数
private final Parser<T> parser;
public ProtoDeserializer() {
Class<?> subclass = this.getClass();
try {
ParameterizedType pType = (ParameterizedType) subclass.getGenericSuperclass();
Class<T> tClass = (Class<T>) pType.getActualTypeArguments()[0];
// In the case where the constructor for `T` takes no arguments.
parser = tClass.newInstance().getParserForType();
} catch(Throwable t) {
throw new RuntimeException("Subclass not compatible", t);
}
}
只要 subclass 直接使用具体类型参数实现 ProtoDeserializer
,这就可以工作。即:
class MyDeserializer extends ProtoDeserializer<MyMessage> {...}
我正在尝试编写一个通用的 java class 可用于 deserialize/parse 任何 protobuf 消息。
代码在完美世界中应该是这样的:
public abstract class ProtoDeserializer<T extends Message> {
public T deserialize(final byte[] bytes) throws Exception {
Parser<T> parser = T.getParserForType(); // Syntax Error: this method is not static!
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
但是,我无法获得通用 protobuf 消息的正确解析器。实现这种通用 class 的正确方法是什么?
最简单的是将解析器作为参数传递给构造函数:
public abstract class ProtoDeserializer<T extends Message> {
private final Parser<T> parser;
public ProtoDeserializer(Parser<T> parser) {
this.parser = parser;
}
public T deserialize(final byte[] bytes) throws Exception {
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
Passing the parser is my current workaround. But it would be nice to avoid it, because it's redundant information.
对你来说可能是多余的,但对compiler/runtime来说并不多余。
如果您认为可以创建 class 的原始实现:
ProtoDeserializer proto = new ProtoDeserializer() {
...
};
类型 T
必须来自 某个地方 。
这只是被擦除泛型的现实。如果您需要泛型参数的类型信息,则必须手动提供。
您可以尝试的另一个 hack 是从实现子 class:
中获取具体类型参数private final Parser<T> parser;
public ProtoDeserializer() {
Class<?> subclass = this.getClass();
try {
ParameterizedType pType = (ParameterizedType) subclass.getGenericSuperclass();
Class<T> tClass = (Class<T>) pType.getActualTypeArguments()[0];
// In the case where the constructor for `T` takes no arguments.
parser = tClass.newInstance().getParserForType();
} catch(Throwable t) {
throw new RuntimeException("Subclass not compatible", t);
}
}
只要 subclass 直接使用具体类型参数实现 ProtoDeserializer
,这就可以工作。即:
class MyDeserializer extends ProtoDeserializer<MyMessage> {...}