Nik*_*kov 19 haskell attoparsec aeson
在我的应用程序上工作我偶然发现Aeson无法解码UTF8输入的问题.深入挖掘我发现它依赖于Parser ByteStringAttoparsec,这似乎是问题的根源.但实际上并不是我在这里问的问题.
事情是它不是我见过人们使用的唯一地方ByteString,因为对我来说似乎很明显,只是Text合适的,因为JSON不是一些二进制文件,它是一个可读的文本,它可能很好地包含UTF8字符.
所以我想知道我是否遗漏了某些东西并且有正当理由可以选择ByteString,Text或者这只是一种普遍存在的错误的图书馆设计现象,这是因为大多数人对拉丁语中任何其他角色的关注较少.
Dan*_*her 21
我认为你的问题只是一个误解.
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.\"}"
Run Code Online (Sandbox Code Playgroud)
当您print使用包含a的值时String,将使用Show实例for Char,并且该代码点的所有字符都会超过127.要获取所需的字形,您需要putStr[Ln]使用String.
所以aeson正确解码了utf8编码的输入,正如所期望的那样,因为它对值本身进行了utf8编码:
encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .
{-# SCC "toJSON" #-} toJSON
Run Code Online (Sandbox Code Playgroud)
所以问题为什么aeson使用ByteString而不是Text编码的最终目标和解码的起点.
因为那是合适的类型.编码值旨在在机器之间移植.这发生在一个字节流(八位字节,如果我们处于迂腐的情绪).这正是ByteString提供的,然后必须以特定于应用程序的方式处理一系列字节.出于此目的aeson,字节流应以utf-8编码,并aeson假定decode函数的输入有效utf-8,并将其输出编码为有效的utf-8.
传输例如Text会遇到可移植性问题,因为16位编码取决于字节顺序,因此Text不适合在机器之间交换数据.注意,在编码时(并且可能在解码时)aeson使用Text作为中间类型,因为这是在中间阶段使用的适当类型.