20

在我的应用程序上工作时,我偶然发现了Aeson 无法解码 UTF8 input的问题。深入挖掘我发现它依赖于Parser ByteStringAttoparsec,这对我来说似乎是问题的根源。但这实际上不是我在这里要问的。

问题是它不是我见过人们使用的唯一地方ByteString,这对我来说似乎很明显,只有Text合适的地方,因为 JSON 不是一些二进制文件,它是可读的文本,它很可能包含 UTF8 字符。

所以我想知道我是否遗漏了一些东西并且有正当的理由可以选择ByteStringText或者这只是由于大多数人不太关心拉丁文以外的任何其他字符集而导致的糟糕库设计的普遍现象。

4

1 回答 1

22

我认为你的问题只是一个误解。

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的值包含 aString时,将使用Showfor 的实例,并转义所有代码点高于 127 的字符。要获得所需的Char字形,您需要.putStr[Ln]String

如此aeson正确地解码了 utf8 编码的输入,正如预期的那样,因为它对值本身进行了 utf8 编码:

encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .
         {-# SCC "toJSON" #-} toJSON

那么对于为什么aeson使用ByteString而不是Text用于编码的最终目标和解码的起点的问题。

因为那是合适的类型。编码值旨在在机器之间可移植地传输。这以字节流的形式发生(八位字节,如果我们处于迂腐的心情)。这正是 a 所ByteString提供的,然后必须以特定于应用程序的方式处理的字节序列。出于 的目的aeson,字节流应以 utf-8 编码,并aeson假设decode函数的输入是有效的 utf-8,并将其输出编码为有效的 utf-8。

传输 egText会遇到可移植性问题,因为 16 位编码取决于字节顺序,因此Text不是机器之间数据交换的合适格式。请注意,在编码时(可能也在解码时)aeson用作Text中间类型,因为这是在中间阶段使用的合适类型。

于 2012-12-29T17:21:54.497 回答