Ответ 1
Я думаю, ваша проблема - просто недоразумение.
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
как промежуточный тип при кодировании (и, предположительно, также при декодировании), потому что это подходящий тип для использования на промежуточных этапах.