Декодировать объекты utf8 из json в utf8 С++

У меня есть строка с объектами utf8 (я не уверен, что правильно назвал ее):

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";

Как я мог преобразовать его в нечто более читаемое? Я использую g++ с поддержкой С++ 11, но после нескольких часов работы в руководстве std :: codecvt я не получаю никакого результата:

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";

wstring_convert<codecvt_utf8_utf16<char16_t>,char16_t> convert; 
string dest = convert.to_bytes(std); 

возвращает кошмар stacktrace, начинающийся с:

error: no matching function for call to ‘std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>::to_bytes(std::string&)

Надеюсь, есть другой путь.

+2
источник поделиться
2 ответа

Во-первых, ваше использование std::wstring_convert обратное. У вас есть кодированная std::string, кодированная UTF-8, которую вы хотите преобразовать в широкую строку Unicode. Вы получаете ошибку компилятора, потому что to_bytes() не принимает std::string качестве входных данных. Он принимает std::wstring_convert::wide_string как вход (который является std::u16string в вашем случае из-за использования char16_t в специализации), поэтому вам нужно использовать from_bytes() вместо to_bytes():

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";

std::wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> convert; 
std::u16string dest = convert.from_bytes(std);

Теперь, говоря, что в разделе 9 спецификации JSON говорится:

9 Строка

Строка представляет собой последовательность кодовых точек Unicode, заключенных в кавычки (U + 0022). Все символы могут быть помещены в кавычки, за исключением символов, которые должны быть экранированы: отметка кавычки (U + 0022), обратное солидус (U + 005C) и управляющие символы U + 0000 до U + 001F. Имеются двухсимвольные представления escape-последовательности некоторых символов.

\" обозначает символ кавычки (U + 0022).

\\ представляет обратный символ солидуса (U + 005C).

\/ представляет символ солидуса (U + 002F).

\b представляет символ обратного пробела (U + 0008).

\f представляет символ подачи формы (U + 000C).

\n представляет символ линии (U + 000A).

\r представляет символ возврата каретки (U + 000D).

\t представляет символ табуляции символов (U + 0009).

Так, например, строка, содержащая только один обратный символ солидуса, может быть представлена как " \\ ".

Любая кодовая точка может быть представлена как шестнадцатеричное число. Значение такого числа определяется ISO/IEC 10646. Если кодовая точка находится на базовой многоязычной плоскости (U + 0000 - U + FFFF), то она может быть представлена в виде шестисимвольной последовательности: обратного солидуса, за которым следует строчная буква u, за которой следуют четыре шестнадцатеричные цифры, которые кодируют кодовую точку. Шестнадцатеричные цифры могут быть цифрами (U + 0030 через U + 0039) или шестнадцатеричными буквами от A до F в верхнем регистре (U + 0041 до U + 0046) или в нижнем регистре (U + 0061 через U + 0066). Так, например, строка, содержащая только один обратный символ солидуса, может быть представлена как " \u005C ".

Следующие четыре случая дают одинаковый результат:

" \u002F "

" \u002F "

" \/ "

" / "

Чтобы избежать кодовой точки, которая не находится в базовой многоязычной плоскости, символ представляется в виде двенадцатисимвольной последовательности, кодирующей суррогатную пару UTF-16. Так, например, строка, содержащая только символ ключа G (U + 1D11E), может быть представлена как " \uD834\uDD1E ".

Исходные данные JSON сами могут быть закодированы в UTF-8 (наиболее распространенная кодировка), UTF-16 и т.д. Но независимо от используемой кодировки последовательность символов "\u0418\u043d\u0434\u0435\u043a\u0441" представляет последовательность UTF-16 кода U+0418 U+043d U+0434 U+0435 U+043a U+0441, которая является символьной строкой Unicode "Индекс".

Если вы используете фактический синтаксический анализатор JSON (например, JSON для Modern C++, jsoncpp, RapidJSON и т.д.), Он будет анализировать значения кода UTF-16 для вас и возвращать читаемые строки Unicode.

Но если вы обрабатываете данные JSON вручную, вам придется вручную декодировать любые escape-последовательности \x и \uXXXX. std::wstring_convert не может сделать это для вас. Он может преобразовывать JSON из std::string в std::wstring/std:u16string, если это упрощает анализ данных. Однако вам все равно придется разбирать содержимое JSON отдельно.

Впоследствии, если это необходимо, вы можете использовать std::wstring_convert для преобразования любых извлеченных строк std::wstring/std::u16string обратно в UTF-8 для сохранения памяти.

+2
источник

То, что вы видите, это не объекты, а коды. Вы определяете символы через escape-последовательности Unicode, и компилятор автоматически преобразует их в UTF-8. Типичным способом преобразования этого в UTF-16 и наоборот является следующее:

static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string ws2s(const std::wstring &wstr) {
  std::string narrow = converter.to_bytes(wstr);
  return narrow;
}

std::wstring s2ws(const std::string &str) {
  std::wstring wide = converter.from_bytes(str);
  return wide;
}

Конечно, вы не можете преобразовать исходную строку в другую строку того же типа (std :: string), поскольку она не может содержать такие символы. Вот почему код UTF-16 был преобразован в UTF-8 вашим компилятором в первую очередь.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос