В RFC4627 описан способ идентификации кодировки Unicode, когда спецификация спецификации отсутствует. Это полагалось на первые 2 символа в тексте JSON, чтобы всегда быть символами ASCII. Но в RFC7159 спецификация определяет текст JSON как «ws value ws»; подразумевая, что одно строковое значение также будет действительным. Таким образом, первым символом будет вводная цитата, но затем любой символ Юникода, разрешенный в строке, может следовать. Учитывая, что RFC7159 также препятствует использованию спецификации; и больше не описывает процедуру обнаружения кодировки из первых 4 октетов (байтов), как ее можно обнаружить? UTF-32 должен работать корректно, как описано в RFC4627, потому что первый символ имеет четыре байта и должен быть ASCII, но как насчет UTF-16? Второй (2-байтовый) символ может не содержать нулевой байт, чтобы помочь определить правильную кодировку.Точное определение кодирования JSON
ответ
После взглянуть на реализации, которые я сделал пару лет назад, я могу сказать, что это можно однозначно обнаружить данную схему Unicode от всего один характера, учитывая следующие допущения:
- вход должен быть Unicode
- первый символ должен быть ASCII
- Там не должно быть никакого Bom
Co nsider this:
Предполагая, что первый символ является "["
(0x5B) - ASCII. Тогда мы можем получить эти шаблоны байт:
UTF_32LE: 5B 00 00 00
UTF_32BE: 00 00 00 5B
UTF_16LE: 5B 00 xx xx
UTF_16BE: 00 5B xx xx
UTF_8: 5B xx xx xx
, где «хх» либо EOF
или любой другой байт.
Следует также отметить, что в соответствии с RFC7159 самым коротким действительным JSON может быть только один символ. То есть, это может быть возможно 1, 2 или 4 байта - в зависимости от схемы Unicode.
Так что, если это помогает, вот реализация в C++:
namespace json {
//
// Detect Encoding
//
// Tries to determine the Unicode encoding of the input starting at
// first. A BOM shall not be present (you might check with function
// json::unicode::detect_bom() whether there is a BOM, in which case
// you don't need to call this function when a BOM is present).
//
// Return values:
//
// json::unicode::UNICODE_ENCODING_UTF_8
// json::unicode::UNICODE_ENCODING_UTF_16LE
// json::unicode::UNICODE_ENCODING_UTF_16BE
// json::unicode::UNICODE_ENCODING_UTF_32LE
// json::unicode::UNICODE_ENCODING_UTF_32BE
//
// -1: unexpected EOF
// -2: unknown encoding
//
// Note:
// detect_encoding() requires to read ahead a few bytes in order to deter-
// mine the encoding. In case of InputIterators, this has the consequences
// that these iterators cannot be reused, for example for a parser.
// Usually, this requires to reset the istreambuff, that is using the
// member functions pubseekpos() or pupseekoff() in order to reset the get
// pointer of the stream buffer to its initial position.
// However, certain istreambuf implementations may not be able to set the
// stream pos at arbitrary positions. In this case, this method cannot be
// used and other edjucated guesses to determine the encoding may be
// needed.
template <typename Iterator>
inline int
detect_encoding(Iterator first, Iterator last)
{
// Assuming the input is Unicode!
// Assuming first character is ASCII!
// The first character must be an ASCII character, say a "[" (0x5B)
// UTF_32LE: 5B 00 00 00
// UTF_32BE: 00 00 00 5B
// UTF_16LE: 5B 00 xx xx
// UTF_16BE: 00 5B xx xx
// UTF_8: 5B xx xx xx
uint32_t c = 0xFFFFFF00;
while (first != last) {
uint32_t ascii;
if (static_cast<uint8_t>(*first) == 0)
ascii = 0; // zero byte
else if (static_cast<uint8_t>(*first) < 0x80)
ascii = 0x01; // ascii byte
else if (*first == EOF)
break;
else
ascii = 0x02; // non-ascii byte, that is a lead or trail byte
c = c << 8 | ascii;
switch (c) {
// reading first byte
case 0xFFFF0000: // first byte was 0
case 0xFFFF0001: // first byte was ASCII
++first;
continue;
case 0xFFFF0002:
return -2; // this is bogus
// reading second byte
case 0xFF000000: // 00 00
++first;
continue;
case 0xFF000001: // 00 01
return json::unicode::UNICODE_ENCODING_UTF_16BE;
case 0xFF000100: // 01 00
++first;
continue;
case 0xFF000101: // 01 01
return json::unicode::UNICODE_ENCODING_UTF_8;
// reading third byte:
case 0x00000000: // 00 00 00
case 0x00010000: // 01 00 00
++first;
continue;
//case 0x00000001: // 00 00 01 bogus
//case 0x00000100: // 00 01 00 na
//case 0x00000101: // 00 01 01 na
case 0x00010001: // 01 00 01
return json::unicode::UNICODE_ENCODING_UTF_16LE;
// reading fourth byte
case 0x01000000:
return json::unicode::UNICODE_ENCODING_UTF_32LE;
case 0x00000001:
return json::unicode::UNICODE_ENCODING_UTF_32BE;
default:
return -2; // could not determine encoding, that is,
// assuming the first byte is an ASCII.
} // switch
} // while
// premature EOF
return -1;
}
}
Спасибо за код. Мой исходный код следовал процедуре, описанной в RFC4627, который смотрит на первые 4 байта следующим образом: 00 00 00 хх UTF-32BE, 00 хх 00 хх UTF-16BE, хх 00 00 00 UTF-32LE, хх 00 xx 00 UTF-16LE, xx xx xx xx UTF-8. С RFC 7159, допускающим однострочное значение, можно использовать что-то вроде 00 xx xx 00 или xx 00 00 xx, когда используется UTF-16. Так что я просто изменил мою следующим образом: 00 00 00 хх UTF-32BE, хх 00 00 00 UTF-32LE, 00 хх UTF-16BE, хх 00 UTF-16LE, все остальное UTF-8. Насколько я вижу, ваш код должен работать так, как есть. –
- 1. Clojure: точное определение редуктора
- 2. Каково точное определение «токена»?
- 3. Точное определение термина 'marshalling'
- 4. Каково точное определение замыкания?
- 5. PHP mime точное определение
- 6. Определение кодирования цвета JPEG
- 7. Какое точное определение Metacircular Interpreter?
- 8. Каково точное определение набора данных?
- 9. Точное определение вида в android
- 10. Каково точное определение переменной экземпляра?
- 11. Точное определение местоположения в помещении с помощью андроида - недостаточно точное
- 12. Определение схемы кодирования текстового файла
- 13. Точное определение форматирования с плавающей строкой?
- 14. Основное покрытие блока - каково точное определение?
- 15. Точное определение: if ($ variable) {...} в PHP
- 16. Какое точное определение веса сбалансированного дерева?
- 17. Точное определение матриц в OpenCv StereoRectify
- 18. Точное определение количества исполнений в программе
- 19. Какое точное определение шаблона проектирования стратегии?
- 20. для петли в ржавчине - точное определение?
- 21. Проверить точное json в jmeter
- 22. JSON кодирования массива
- 23. Python JSON вопросам кодирования
- 24. Golang кодирования/JSON упаковщик
- 25. Json кодирования/декодирования вопросы
- 26. JSON кодирования - специальные символы
- 27. PHP формате JSON кодирования
- 28. JSON кодирования браузером
- 29. IOS: JSON проблемы кодирования
- 30. JSON кодирования выводит результат
Интересный вопрос. Разумеется, определение схемы Unicode является более сложной задачей. Например, один байт, значение ASCII которого является цифрой, также является допустимым JSON: его одноразрядное число в UTF-8. Как насчет предложения решения, и мы можем обсудить ваше решение? – CouchDeveloper
Боюсь, у меня нет предложения, которое будет надежным. Очевидно, сначала нужно проверить спецификацию на всякий случай. Следующая проверка для UTF-32 - если первые 3 байта равны нулю, то это UTF-32BE, иначе, если 3 байта после первого - это нули, это UTF-32LE. До сих пор мы должны были опираться на тест, но теперь возникает проблема. Чтобы проверить UTF-16, нам все равно придется искать 4 байта. Если бы мы могли предположить, что первые 2 символа всегда ASCII, то мы проверяем, являются ли первый и третий байты нулями для UTF-16BE, а второй и четвертый для UTF-16LE. Но если второй символ может быть не-ASCII, что тогда? –
Помогло бы, если бы я дал вам головной убор с реализацией на C++ для обнаружения кодировки? Насколько я знаю, вам не требуется обнаружение спецификации, но я тоже реализовал его на C++. – CouchDeveloper