在使用我的应用程序时,我偶然遇到了Aeson not decoding UTF8 input问题。深入研究发现,它依赖于Attoparsec的 Parser ByteString ,这似乎是我遇到的问题的根源。但这实际上不是我要问的。

事实是,这不是我见过的唯一使用oj​​it_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时,将使用ShowChar实例,该实例将转义码点大于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用作中间类型,因为这是在中间阶段使用的适当类型。

09-26 12:21