Почему разработчики библиотек используют ByteString там, где кажется подходящим Text?
Работая над своим приложением, я столкнулся с проблемой того, что Aeson не расшифровывает ввод UTF8. Копая глубже, я обнаружил, что он опирается на Parser ByteString
Аттопарсек, который, кажется, источник проблемы для меня. Но на самом деле это не то, о чем я здесь спрашиваю.
Дело в том, что это не единственное место, где я видел людей, использующих ByteString
где, как мне кажется очевидным, только Text
это уместно, поскольку JSON - это не какой-то двоичный файл, это читаемый текст, который может содержать символы UTF8.
Поэтому мне интересно, что я что-то упустил, и есть ли веские причины для выбора ByteString
над Text
или это просто широко распространенное явление плохого дизайна библиотеки, вызванное тем, что большинство людей меньше заботятся о любых других наборах символов, чем латинский.
2 ответа
Я думаю, что ваша проблема просто недоразумение.
Prelude> print "Ёжик лижет мёд."
"\1025\1078\1080\1082 \1083\1080\1078\1077\1090 \1084\1105\1076."
Prelude> putStrLn "\1025\1078\1080\1082 \1083\1080\1078\1077\1090 \1084\1105\1076."
Ёжик лижет мёд.
Prelude> "{\"a\": \"Ёжик лижет мёд.\"}"
"{\"a\": \"\1025\1078\1080\1082 \1083\1080\1078\1077\1090 \1084\1105\1076.\"}"
Когда ты print
значение, содержащее String
, Show
экземпляр для Char
используется и экранирует все символы с кодами выше 127. Чтобы получить нужные глифы, вам нужно putStr[Ln]
String
,
Так aeson
правильно декодированный ввод в кодировке utf8, как и следовало ожидать, поскольку он сам кодирует значения utf8:
encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .
{-# SCC "toJSON" #-} toJSON
Так что на вопрос, почему aeson
использования ByteString
и не Text
для конечной цели кодирования и начальной точки декодирования.
Потому что это подходящий тип. Закодированные значения предназначены для переноса между машинами. Это происходит как поток байтов (октетов, если мы находимся в педантичном настроении). Это именно то, что ByteString
обеспечивает последовательность байтов, которые затем должны обрабатываться в зависимости от приложения. Для целей aeson
поток байтов должен быть закодирован в utf-8, и aeson
предполагает ввод decode
функция действительна utf-8, и кодирует свой вывод как действительный utf-8.
Передача например Text
столкнется с проблемами переносимости, поскольку 16-битная кодировка зависит от порядка байтов, поэтому Text
не подходит для обмена данными между машинами. Обратите внимание, что aeson
использования Text
как промежуточный тип при кодировании (и, вероятно, также при декодировании), потому что это подходящий тип для использования на промежуточных этапах.
Стандарт JSON основан на UTF-16, а не UTF-8. Более подробная информация доступна на официальном сайте, http://json.org/. (И в дальнейшей защите Aeson двоичные биты JSON не открываются через его интерфейс: String
конструктор Value
содержит Text
не ByteString
.)