如何在java程序中对protobuf-net序列化的数据进行反序列化

时间:2017-11-02 03:01:49

标签: java c# serialization protocol-buffers

数据由c#protobuf-net序列化并设置为redis, 现在我想获取数据并在java程序中反序列化,一切正常,期望日期时间字段,它们无法正确序列化。 在c#程序中,数据从实体序列化如下,并设置为redis

[Serializable]
[ProtoContract]
public class TestMsg 
{
    public TestMsg();
    [ProtoMember(1)]
    public string message { get; set; }
    [ProtoMember(2)]
    public DateTime UpdateTime { get; set; }
}

在我的java程序中,proto flie如下:

syntax = "proto2";
option java_outer_classname = "TestMsgEntity";
message TestMsg {
    required string Message = 1;//
    required string UpdateTime = 2;// it can not be deserialized properly.if I change is to long,then i get zero .
}

// java code

byte[]  byteArrayRedis  = provider.getbyte("keyname"); //get the data from redis

ByteArrayInputStream baiContent = new ByteArrayInputStream(byteArrayRedis);
try {
        TestMsgEntity.TestMsg msg = TestMsgEntity.TestMsg.parseFrom(baiContent);
        String message = msg.getMessage (); //it is ok
        String lastUpdate =msg.getLastUpdateTime();//how can i get the value? 
    }

1 个答案:

答案 0 :(得分:1)

最近有一些新的“众所周知的”合同来描述时代。最好的办法是在java .proto中使用“timestamp”,并通过WellKnown使用[ProtoMember]数据格式注释DateTime成员。

要更简单地看到这一点:编写一个使用“timestamp”的.proto(无论如何你需要为java做),并通过https://protogen.marcgravell.com运行它以查看它输出的内容。以下是.proto的修改版本,因此您只需点击“生成”:https://protogen.marcgravell.com/#g38c45fbb1730d14bc4d560a13f61d2a3 - 如您所见,关键位是:

[global::ProtoBuf.ProtoMember(2,
    DataFormat = global::ProtoBuf.DataFormat.WellKnown, IsRequired = true)]
public global::System.DateTime? UpdateTime { get; set; }

DataFormat = global::ProtoBuf.DataFormat.WellKnown告诉它使用timestamp表示法。同样,这会导致TimeSpan使用众所周知的duration表示法。

如果你有protobuf-net存储的预先存在的数据而没有众所周知的格式,那么你必须通过bcl.proto手动解码它;我很抱歉它不是那么简单,但是:它需要某种东西,而当时并不存在“众所周知”。