Haskell 哈斯克尔。MongoDB驱动程序或Aeson字符集问题

Haskell 哈斯克尔。MongoDB驱动程序或Aeson字符集问题,haskell,mongodb,Haskell,Mongodb,您好,我在mongodb数据库中填充了一些数据,我确保数据存储在正确的字符集中,为了获取数据,我使用了以下代码段: {-# LANGUAGE OverloadedStrings #-} import Network.Wai import Network.Wai.Handler.Warp (run) import Data.Enumerator (Iteratee (..)) import Data.Either (either) import Control.Monad (join) impor

您好,我在mongodb数据库中填充了一些数据,我确保数据存储在正确的字符集中,为了获取数据,我使用了以下代码段:

{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Warp (run)
import Data.Enumerator (Iteratee (..))
import Data.Either (either)
import Control.Monad (join)
import Data.Maybe (fromMaybe)
import Network.HTTP.Types (statusOK, status404)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Lazy.Char8 (pack)
import qualified Data.Text.Lazy as T
import Data.Text (Text(..))
import Control.Monad.IO.Class (liftIO, MonadIO)
import Data.Aeson (encode)
import qualified Data.Map as Map
import qualified Database.MongoDB as DB

application dbpipe req = do
  case unpack $ rawPathInfo req of
    "/items" -> itemsJSON dbpipe req
    _ ->  return $ responseLBS status404 [("Content-Type", "text/plain")] "404"

indexPage :: Iteratee B.ByteString IO Response
indexPage = do
  page <- liftIO $ processTemplate "templates/index.html" []
  return $ responseLBS statusOK [("Content-Type", "text/html; charset=utf-8")] page

processTemplate f attrs = do
  page <- L.readFile f
  return page

itemsJSON :: DB.Pipe -> Request -> Iteratee B.ByteString IO Response
itemsJSON dbpipe req = do
  dbresult <- liftIO $  rundb dbpipe $ DB.find (DB.select [] $ tu "table") >>= DB.rest
  let docs = either (const []) id dbresult
--  liftIO $ L.putStrLn $ encode $ show $ map docToMap docs
  return $ responseLBS statusOK [("Content-Type", "text/plain; charset=utf-8")]
    (encode $ map docToMap docs)

docToMap doc = Map.fromList $ map (\f -> (T.dropAround (== '"') $ T.pack $ show $ DB.label f, T.dropAround (== '"') $ T.pack $ show $ DB.value f)) doc


main =  do
  pipe <- DB.runIOE $ DB.connect $ DB.host "127.0.0.1"
  run 3000 $ application pipe

rundb pipe act = DB.access pipe DB.master database act

tu :: B.ByteString -> UString
tu = DB.u . C8.unpack
这发生在我试图打印数据的情况下,也发生在我返回编码为JSON的数据的情况下
您知道如何正确地从MongoDB驱动程序中提取值吗?

一切都按预期进行--只有您的预期是错误的。=)

你看到的不是原始的
String
s;它们是
String
,已通过
show
函数(由
print
调用)转义为仅存在于可打印ASCII范围内:

print = putStrLn . show

不要害怕:在内存中,
打印为
“\1058”
的字符串实际上是一个Unicode码长。您可以通过打印感兴趣的
字符串之一的长度,并将其与预期的Unicode码点数进行比较来观察这一点。

以下行确认aeson的编码工作正常(使用utf8字符串库将utf8数据从lazy bytestring读回haskell字符串:

> putStrLn $ Data.ByteString.Lazy.UTF8.toString $ encode $ ("\1058\1080\1087 \1087\1086\1076",12)
["Тип под",12]
仔细查看您的代码,我看到了真正的问题。您正在调用
T.pack$show$DB.value
——这将显示为文字代码点,然后将其打包到文本对象中。解决方法是从show切换到更智能的程序。看看这个(未测试)

显然,要处理递归情况等,您需要比这更聪明,但这是一般的概念


事实上,“最好的”要做的事情是直接编写
BSON->JSON
函数,而不是通过任何中间结构。

谢谢,这是一个很好的解释,但我仍然不知道如何从数据库中获取普通字符串。我尝试了DB.cast,但它也不起作用。或者更简单的情况是如何转换MongoDB
UString
Text
我不知道,我还没有使用该库。但在我看来,您上面粘贴的代码似乎已经转换成
字符串了。问题在于调用
print
(而不是
putStrLn
或类似程序),不在数据库界面中。我的应用程序将结果交给aeson的编码,并且生成的JSON数据中也填充了该代码点,这是不可接受的。用户只需要简单的UTF8字符串,而不是转义码。@Dfr也许你最好提出另一个问题,用一个简化的示例说明某些aeson代码不符合你的要求。@Dfr编辑版本sion仍然没有直接显示json的问题。我看到您提出了正确的解决方案,但无法让您的代码片段适用于我的情况,例如为什么将字符串构造函数用于DB.Value type?@Dfr:因为这是bson使用的构造函数的名称,这就是
Value
的含义:我不打算安装mongodb绑定现在,很抱歉这段代码没有经过测试。不过,要点应该是正确的。谢谢你,smartShow
终于成功了,恐怕我的haskell知识还太差,无法实现一般的BSON->JSON函数。
> putStrLn $ Data.ByteString.Lazy.UTF8.toString $ encode $ ("\1058\1080\1087 \1087\1086\1076",12)
["Тип под",12]
smartShow :: DB.Value -> Text
smartShow (String s) = Data.Text.Encoding.decodeUtf8 $ Data.CompactString.UTF8.toByteString s
smartShow x = T.pack $ show x