为什么图书馆设计师使用ByteString,其中Text似乎合适?

时间:2012-12-29 10:13:01

标签: haskell attoparsec aeson

在我的应用上工作时,我偶然发现了Aeson not decoding UTF8 input的问题。深入挖掘我发现它依赖于Attoparsec的Parser ByteString,这对我来说似乎是问题的根源。但实际上并不是我在这里问的问题。

问题是我不是唯一一个看过人们使用ByteString的地方,因为我觉得只有Text是合适的,因为JSON不是一些二进制文件,它是一个可读的文本,它可能包含UTF8字符。

所以我想知道我是否遗漏了某些东西并且有正当理由选择ByteString而不是Text,或者这只是一个普遍存在的图书馆设计糟糕的现象,因为大多数人都缺少照顾关于除拉丁之外的任何其他角色集。

2 个答案:

答案 0 :(得分:21)

我认为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的{​​{1}}实例,并且会转义代码点数大于127的所有字符。你想要的字形,你需要Char putStr[Ln]

所以String正确解码了utf8编码的输入,应该是预期的,因为它对值本身进行了utf8编码:

aeson

所以问题为什么encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue . {-# SCC "toJSON" #-} toJSON 使用aeson而非ByteString作为编码的最终目标和解码起点。

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

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

答案 1 :(得分:2)

JSON标准已经确定了UTF-16,而不是UTF-8。更多详细信息,请访问官方网站http://json.org/。 (为了进一步防御Aeson,JSON的二进制位不会通过其接口公开:String的{​​{1}}构造函数包含Value,而不是Text。 )