haskell - ハスケル。 MongoDBドライバーまたはAeson文字セットの問題

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)
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


次に、結果は驚くべきものです。DB.labelはうまく機能しますが、DB.valueはいくつかのエスケープコードとしてネイティブ文字を提供するため、結果は次のようになります。

curl http://localhost:3000/itemsは以下を与えます:

[{"Марка": "\1058\1080\1087 \1087\1086\1076",
  "Model": "BD-W LG BP06LU10 Slim \1058\1080\1087 \1087\1086\1076\1082\1083\1102\1095\1077\1085\1080\1103"},
 ...
]


これは、データを印刷しようとした場合と、JSONとしてエンコードされたデータを返した場合に発生します
MongoDBドライバーから値を正しく抽出する方法はありますか?
答え
次の行は、aesonのエンコーディングが適切に機能することを確認しています(utf8文字列ライブラリを使用して、レイジーバイト文字列からutf8データを読み取り、haskell文字列に戻します:

> putStrLn $ Data.ByteString.Lazy.UTF8.toString $ encode $ ("\1058\1080\1087 \1087\1086\1076",12)
["Тип под",12]


コードをより詳しく見ると、実際の問題がわかります。あなたはT.pack $ show $ DB.valueを呼び出しています-これはリテラルコードポイントとしてレンダリングされ、それらをテキストオブジェクトにパックします。修正は、ショーからよりスマートなものに切り替えることです。これを見てください

smartShow :: DB.Value -> Text
smartShow (String s) = Data.Text.Encoding.decodeUtf8 $ Data.CompactString.UTF8.toByteString s
smartShow x = T.pack $ show x


再帰的なケースなどを処理するには明らかにそれよりも賢くする必要がありますが、それは一般的な概念です...

実際、「最善の」ことは、中間構造をまったく経由するのではなく、BSON -> JSONの関数を直接記述することです。
関連記事

haskell - ソースコードにアクセスせずにGHCiを使用してモジュールをロードする

haskell - yesodをインストールできません

haskell - このHappstackフォームコードの一部をリファクタリングする方法はありますか?

performance - collat​​zチェーンのパフォーマンスの問題

haskell - 独自のデータ型をモナド関数チェーンの戻り値として定義する方法は?

haskell - 型クラスによる関数型シグネチャのクリーンアップ

haskell - Haskellの可変ヒープ構造

haskell - Yesodがインストールに失敗する(つまり、テキストパッケージ)

haskell - wxHaskellのラベルが全文を表示できない

haskell - Haskellでのリストの結合