CBOR-сериализация (экранирование строки)

Я выполнял сериализацию CBOR объекта JSON в C++ с помощью библиотеки nlohmann::json, и мой сценарий использования заключается в чтении вывода строки байта cbor в C#. Я заметил, что, хотя при выгрузке объекта json в строку в C++ с помощью библиотеки nlohmann::json, строковые значения json (т.е. case value_t::string) экранируются (делается вызов escape_string), такого вызова нет создается, когда значения json являются строковыми значениями в подходе CBOR.

Я читал CBOR CRF 7049, и кажется, что строки не нужно экранировать при сериализации в CBOR. Поведение в библиотеке nlohmann::json непротиворечиво: строки не экранируются при сериализации и не исключаются при экранировании при десериализации. Но похоже, что Newtonsoft.Json (библиотека C#) ожидает этого. Это действительное ожидание? Или я что-то не так делаю в процессе?

Сторона C++:

nlohmann::json json_doc;
json_doc["characters"] = nlohmann::json::array();

for (int i = 0; i < characters.size(); i++) {
    json_doc["characters"][i]["name"] = (characters[i] != nullptr) ? characters[i]->name() : "";
}

std::vector<uint8_t> cbor = nlohmann::json::to_cbor(json_doc);
output->assign((char*)&cbor[0], cbor.size());

Сторона C#. cbor_bytes - строка байтов cbor (выходной вектор C++)

CBORObject cbor = CBORObject.DecodeFromBytes(cbor_bytes);
output = cbor.ToString();

Такая выходная строка к тому времени неправильно сформирована:

{"characters": [{"name": "Clara Oswald"}, {"name": "Kensi Blye"}, {"name": "Temperance "Bones" Brennan"}]}

и, очевидно, не может быть проанализирован:

JObject output_obj = JObject.Parse(output);

1 ответ

Решение

CBOR (краткое представление двоичных объектов) не является JSON (нотация объектов JavaScript). Хотя CBOR, возможно, заимствовал некоторые концепции из JSON, это явно другой формат с другими правилами и целями. CBOR - это двоичный формат; JSON - это текст. В CBOR строки имеют префиксы длины, тогда как в JSON их нет. Кроме того, CBOR не допускает произвольных пробелов между элементами (это не имеет смысла для двоичного формата), в то время как JSON делает (для удобства чтения). В конечном счете, CBOR не нужен механизм для экранирования строк, поскольку он не требует разделителей, чтобы указать, где строка начинается и заканчивается. JSON, с другой стороны, требует двойных кавычек, чтобы отметить начало и конец каждой строки. Как следствие, кавычки и управляющие символы в строках должны быть экранированы с помощью обратной косой черты в JSON, а также сами литеральные обратные косые черты. Невозможно обойти это правило, если вы хотите убедиться, что JSON будет обрабатываться.

В приведенном выше коде вы используете CBORObject.ToString() способ превратить объект в строку. Если это CBORObject из сторонней библиотеки, в документации указано, что ToString() будет производить действительный JSON? Если так, то это определенно имеет ошибку; он должен делать правильное экранирование, как того требует спецификация JSON. Если такого обещания действительного JSON нет, вы не можете ожидать, что Json.Net сможет проанализировать строку, даже если она будет выглядеть как JSON. (Вы можете проверить, CBORObject имеет какой-то другой специальный метод, как ToJson() для выполнения этого преобразования.) Если CBORObject это ваш собственный код, поэтому вы должны правильно экранировать строки при конвертации из CBOR в JSON.

Другие вопросы по тегам