如何将protobuf字节数组反序列化为java对象

问题描述 投票:0回答:1

protobuf 新手,需要您的建议。

我有一个 JMS 订阅者,它正在从 TIBCO 队列接收消息(类型 -> com.tibco.tibjmsTibjmsBytesMessage)。这些消息已作为 Protobuf 字节消息发布到队列上。作为订阅者,我已将这些 bytesMessage 转换为字节数组。由于我有 protobuf 消息的 JAVA 类 protoFile.class,因此为了反序列化字节数组,我调用 protoFile.parseFrom(byte[] data) 函数。然而,在响应中我看到所有字段的值都是空的。

有人可以建议遗漏了什么吗? 我需要的只是从 Protobuf 字节消息中读取数据并将它们分配给 java 对象。 我没有 proto 文件的架构,只有 proto 文件的已编译 JAVA 类,即 protoFile.class

蒂亚!

java deserialization protocol-buffers tibco-ems protobuf-java
1个回答
0
投票

protobuf 消息在数据流中没有类名。我认为这样做是因为来源语言可能与接收者的语言不同。接收端点将期望给定类型并具有原始生成的代码来转换它。如果您将两端都限制为 Java,则可以将类名与数据一起发送。您甚至可以使用另一个原始消息来做到这一点。然后假设所有消息都是该类型。真正的消息和类型包含在该消息中。然后你就有了类名和数据。这是 Jms 的 MessageConverter,您可以获取适合您情况的部分内容。

原型文件

syntax = "proto3";
package jms;

option java_package = "some.package.here.jms";
option java_multiple_files = true;

message AnyMessage{
  string classname = 1;
  bytes bytesData = 2;
}

代码

@Slf4j
public class ProtobufJmsMessageConverter implements MessageConverter {

@Override
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
    GeneratedMessageV3 protoMsg = (GeneratedMessageV3) object;
    
    AnyMessage wrap = AnyMessage.newBuilder().setClassname(object.getClass().getName()).setBytesData(protoMsg.toByteString()).build();
            
    BytesMessage bytesMessage = session.createBytesMessage();
    bytesMessage.writeBytes(wrap.toByteArray());
    return bytesMessage;
}

@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
    BytesMessage bytesMessage = (BytesMessage) message;
    int messageLength = (int) bytesMessage.getBodyLength();
    byte[] rawProtoMsg = new byte[messageLength];
    bytesMessage.readBytes(rawProtoMsg);
    try {
        AnyMessage anyMessage = AnyMessage.parseFrom(rawProtoMsg);
        Class protoClass = Class.forName(anyMessage.getClassname());
        
        Method m = protoClass.getMethod("parseFrom", byte[].class);
        Object result = m.invoke(null, anyMessage.getBytesData().toByteArray());
        return result;
    } catch (InvalidProtocolBufferException | ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        log.error("",e);
        throw new MessageConversionException("Only AnyMessage should be sent.", e);
    }
}

}
© www.soinside.com 2019 - 2024. All rights reserved.