Сериализация карты фиксированного размера в CBOR
У меня есть следующий JSON:
[
{
2: {
"c": true
}
},
{
3: {
"p": 10
}
}
]
Это я хотел бы преобразовать в формат CBOR. В соответствии с cbor.me у меня есть следующий вывод:
82A102A16163F5A103A161700A
Но, при использовании Jackson Binary CBOR Serializer, я получаю следующий вывод:
82BF02BF6163F5FFFFBF03BF61700AFFFF
Что не так, но не оптимизировано... У меня есть дополнительные 4 ненужных байта, добавленных к тому, что это действительно может быть.
Затем я попытался вручную сериализовать JSON, но тот же результат:
@Override
public void serialize(Request value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartArray(value.getDataList().size());
for (Data data : value.getDataList()) {
jgen.writeStartObject(new Map[1]);
jgen.writeFieldId(data.getItem());
jgen.writeStartObject();
if (data.getObject().getC() != null) {
jgen.writeBooleanField("c", data.getObject().getC());
}
if (data.getObject().getP() != null) {
jgen.writeNumberField("p", data.getObject().getP());
}
jgen.writeEndObject();
jgen.writeEndObject();
}
jgen.writeEndArray();
}
Это ошибка с библиотекой двоичного формата Jackson или мне не хватает некоторых свойств конфигурации из ObjectMapper?
РЕДАКТИРОВАТЬ: Кажется, это известная проблема: https://github.com/FasterXML/jackson-dataformats-binary/issues/3
1 ответ
Используя версию 2.9.4
следующий метод доступен в CBORGenerator
учебный класс: public final void writeStartObject(int elementsToWrite)
@Override
public void serialize(Request value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartArray(value.getDataList().size());
for (Data data : value.getDataList()) {
((CBORGenerator) jgen).writeStartObject(1);
jgen.writeFieldId(data.getItem());
((CBORGenerator) jgen).writeStartObject(1);
if (data.getObject().getC() != null) {
jgen.writeBooleanField("c", data.getObject().getC());
}
if (data.getObject().getP() != null) {
jgen.writeNumberField("p", data.getObject().getP());
}
jgen.writeEndObject();
jgen.writeEndObject();
}
jgen.writeEndArray();
}
И у меня есть следующий вывод:
82A102A16163F5A103A161700A
Вы уже получили ответ, используя более новый или лучший кодировщик. Но для всех, кто придет сюда позже...
Проблема в том, что кодировщик OP использовал карты неопределенной длины, затем примитивы "BREAK" были разбиты и перешли к следующему элементу.
Сравните версию с примитивами разрыва:
82 # array(2)
BF # map(*)
02 # unsigned(2)
BF # map(*)
61 # text(1)
63 # "c"
F5 # primitive(21)
FF # primitive(*)
FF # primitive(*)
BF # map(*)
03 # unsigned(3)
BF # map(*)
61 # text(1)
70 # "p"
0A # unsigned(10)
FF # primitive(*)
FF # primitive(*)
К версии без них:
82 # array(2)
A1 # map(1)
02 # unsigned(2)
A1 # map(1)
61 # text(1)
63 # "c"
F5 # primitive(21)
A1 # map(1)
03 # unsigned(3)
A1 # map(1)
61 # text(1)
70 # "p"
0A # unsigned(10)
Вы видите карту (*) и карту (1)?
При использовании карт определенной длины вместо неопределенной длины в результирующем CBOR можно использовать "Одна карта идет, вот она" вместо "IDK! Карты идут! Вот одна! Теперь остановись!"
Во втором примере все еще есть примитив, но это не команда BREAK. 0xF5 фактически означает "истина". Уберите первые три бита (основной тип CBOR) из 0xF5 (11110101), и у вас будет десятичный 21 установленный CBOR "истина" (0x00010101).
Кроме того, вполне допустимо присвоить значение 2 в качестве имени карты с "c"="true" внутри него. Но помните, что преобразование в JSON при использовании значений в качестве имен будет проблематичным, если вас это беспокоит.
Это была проблема с плохим кодировщиком, который не должен был использовать карты / разрывы неопределенной длины. Есть время использовать их, но только в "потоковом" режиме, что маловероятно для данного примера. Если у вас есть все элементы заранее и они кодируются, использование неопределенных значений не требуется. Если у вас есть некоторое количество карт, но вы не уверены, сколько их, и хотите начать кодирование того, что у вас есть, тогда вам понадобятся карты или строки неопределенной длины.