在使用我的应用程序时,我偶然遇到了Aeson not decoding UTF8 input问题。深入研究发现,它依赖于Attoparsec的 Parser ByteString
,这似乎是我遇到的问题的根源。但这实际上不是我要问的。
事实是,这不是我见过的唯一使用ojit_code的人的地方,对我来说似乎只有ByteString
是适当的,因为JSON不是二进制文件,它是可读的文本,并且很可能包含UTF8字符。
因此,我想知道是否遗漏了某些东西,并且有充分的理由选择Text
而不是ByteString
,或者这仅仅是图书馆设计不良的普遍现象,其原因是大多数人对拉丁语的关注不及其他任何字符集。
最佳答案
我认为your problem只是一个误会。
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
作为编码的最终目标和解码的起点。因为那是合适的类型。编码值可在机器之间移植。这种情况以字节流的形式发生(八位字节,如果我们处于 Nerd 状态)。这就是
ByteString
所提供的,这是一个字节序列,然后必须以特定于应用程序的方式对其进行处理。就aeson
而言,字节流应以utf-8编码,并且aeson
假定decode
函数的输入为有效的utf-8,并将其输出编码为有效的utf-8。转移例如
Text
会遇到可移植性问题,因为16位编码取决于字节序,因此Text
不是在计算机之间交换数据的合适格式。请注意,aeson
在编码时(大概在解码时也)将Text
用作中间类型,因为这是在中间阶段使用的适当类型。