Я декодирую сообщение MessagePack из конвейера Apache Beam в проекте Java.Я использую Maven для импорта библиотеки MessagePack как зависимости:
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
</dependency>
Я могу использовать это для анализа сообщения MessagePack на пары ключ / значение в Map
, например:
@ProcessElement
public void processElement(ProcessContext c)
{
try
{
Map<Value, Value> map = MessagePack.newDefaultUnpacker(c.element().getPayload()).unpackValue().asMapValue().map();
Карта содержит пару ключ / значение для типа расширения «Timestamp» MessagePack, который выглядит следующим образом и представляет дату / время (см. «Примечание» внизу, для объяснения MessagePackтипы расширения):
UTC=(-1,0x5b-161d46)
Я могу получить это значение 'timestamp', получив значение с помощью ключа UTC
из карты.Я извлекаю его как MessagePack ExtensionValue
, например:
Value date = map.get(ValueFactory.newString("UTC")).asExtensionValue();
date
- это объект, который имеет 2 свойства:
`type` = 1
`data` = `0x5b-161d46`
Как преобразовать data
взначимое представление даты?«Данные» должны переводиться на «текущую» дату, где-то около 16 ноября 2018 года. Это не так просто, как преобразование шестнадцатеричного значения в десятичное.Нужно ли как-то отдельно распаковывать этот data
как-нибудь?Я подозреваю, что 5b-161d46
, вероятно, нужно обрабатывать как байтовый массив, а затем каким-то образом преобразовывать.
Я могу сделать это, чтобы получить data
часть типа расширения в виде байтового массива:
byte[] date = map.get(ValueFactory.newString("UTC")).asExtensionValue().getData();
, что дает мне [91, -22, 29, 70]
... и я могу попытаться распаковать его так:
MessagePack.newDefaultUnpacker(date).unpackValue()
... однако это просто дает мне первый байт(5b
) конвертируется в long
, т.е. 91
И если я попробую любой из них, я получу org.msgpack.core.MessageTypeCastException
, вероятно, потому что unpackValue
просто дает мне одно long
число
MessagePack.newDefaultUnpacker(date).unpackValue().asIntegerValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asMapValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asRawValue();
Я также попробовал следующее:
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(date);
while(unpacker.hasNext()) {
MessageFormat f = unpacker.getNextFormat();
switch(f) {
case POSFIXINT:
case NEGFIXINT: {
int v = unpacker.unpackInt();
break;
}
}
}
Значения в массиве распознаются как POSFIXINT
или NEGFIXINT
, поэтому я могу использовать это для извлечения десятичного целого числазначения для каждого байта в массиве, однако это позволяет мне извлекать элементы в массиве date
как целые числа, и я до сих пор не знаю, как перевести это в дату.
Как мненужно интерпретировать / распаковать эти даты?
Примечание - значение расширения - особый тип MesЗначение sagePack, представленное в виде кортежа, где -1
определяет тип расширения.-1
является зарезервированным расширением для MessagePack timestamp
, а остаток дает шестнадцатеричное значение (0x5b-161d46
):
https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type