I'm decoding a MessagePack message from an Apache Beam pipeline in a Java project. I'm using Maven to import the MessagePack library as dependency:
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
</dependency>
I can use this to parse the MessagePack message it into key/value pairs in a Map
, like this:
@ProcessElement
public void processElement(ProcessContext c)
{
try
{
Map<Value, Value> map = MessagePack.newDefaultUnpacker(c.element().getPayload()).unpackValue().asMapValue().map();
The map contains a key/value pair for a MessagePack 'Timestamp' 'extension' type that looks like this, and which represents a date/time (see the 'Note' at the bottom, for an explanation of MessagePack extension types):
UTC=(-1,0x5b-161d46)
I can get this a 'timestamp' value, by getting the value with the key UTC
, from the map. I retrieve it as a MessagePack ExtensionValue
like this:
Value date = map.get(ValueFactory.newString("UTC")).asExtensionValue();
date
is then an object which has 2 properties:
`type` = 1
`data` = `0x5b-161d46`
How do I convert data
to a meaningful representation of the date? The 'data' should translate to a 'current' date, sometime around 16th November 2018. It's not as simple as converting the hex value to decimal. Do I need to separately unpack this data
somehow? I suspect that 5b-161d46
probably needs to be treated as a byte array and then converted somehow.
I can do this to get the data
part of the extension type as a byte array:
byte[] date = map.get(ValueFactory.newString("UTC")).asExtensionValue().getData();
which gives me [91, -22, 29, 70]
... and I can try to unpack it like this:
MessagePack.newDefaultUnpacker(date).unpackValue()
... however that just gives me the first byte (5b
) converted to a long
i.e. 91
And if I try any of these I get org.msgpack.core.MessageTypeCastException
, probably because unpackValue
just gives me a single long
number
MessagePack.newDefaultUnpacker(date).unpackValue().asIntegerValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asMapValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asRawValue();
I've also tried the following:
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(date);
while(unpacker.hasNext()) {
MessageFormat f = unpacker.getNextFormat();
switch(f) {
case POSFIXINT:
case NEGFIXINT: {
int v = unpacker.unpackInt();
break;
}
}
}
The values in the array are recognised as either POSFIXINT
or NEGFIXINT
, so I can use this to extract decimal integer values for each byte in the array, however that only allows me to extract the elements in the date
array as integers, and I still don't know how to translate that to a date.
How do I need to interpret/unpack these dates?
Note - An extension value is special type of MessagePack value, represented as a tuple where
-1
defines the extension type.-1
is a reserved extension for a MessagePacktimestamp
, and the remainder gives a hex value (0x5b-161d46
):https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type