3

长话短说,我的代码是关于使用 aeson 解析 json文件

这是我的两段代码:

a.hs

{-# LANGUAGE OverloadedStrings #-}

import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as C
import Control.Monad
import Control.Applicative

data AuctionInfo = AuctionInfo {
    realm :: Realm ,
    alliance :: Auctions  ,
    horde ::  Auctions  ,
    neutral :: Auctions  
}   deriving (Show )

instance FromJSON AuctionInfo where
   parseJSON (Object o) = do
      r <- o .: "realm" >>= parseJSON
      a <- o .: "alliance" >>= parseJSON
      h <- o .: "horde" >>= parseJSON
      n <- o .: "neutral" >>= parseJSON
      return $  AuctionInfo r a h n
   parseJSON _ = mzero

data Realm = Realm { name2 :: String , slug:: String} deriving (Show )
instance FromJSON Realm where
      parseJSON (Object o) = Realm <$>
            o .: "name" <*>
            o .: "slug"
      parseJSON _ = mzero

data Auctions = Auctions {auctions :: [Auc]} deriving (Show)
instance FromJSON Auctions where  
      parseJSON (Object o ) = Auctions <$> o.: "auctions"
      parseJSON _ = mzero

data Auc = Auc {
    auc :: Integer,
    itme :: Int,
    owner ::  String,
    bid :: Integer,
    buyout ::Integer,
    quantity :: Int,
    timeLeft :: String,
    rand :: Integer,
    seed :: Integer
    } deriving (Show )

instance FromJSON Auc where
      parseJSON (Object o ) = Auc <$>
            o .: "auc" <*>
            o .: "item" <*>
            o .: "owner" <*>
            o .: "bid" <*>
            o .: "buyout" <*>
            o .: "quantity" <*>
            o .: "timeLeft" <*>
            o .: "rand" <*>
            o .: "seed"
      parseJSON _ = mzero

main = do
    au<- C.readFile "a.json"
    let x = decode au :: Maybe AuctionInfo
    case x of
        Just a -> do
            {-putStrLn.show $ a-}
            putStrLn .show.length.auctions.alliance $ a
            putStrLn "ok"
        Nothing -> putStrLn "fail"

我的json 测试文件

和测试步骤:

  1. 保存代码,并将其命名为 a.hs(或您想要的名称)
  2. 保存测试数据,命名为a.json(不要改名)
  3. 如果你还没有安装aeson$ cabal install aseon
  4. $ ghc a.hs -o a
  5. $ ./a

我从输出中得到的是“失败”。

当我运行命令$ runghc a.hs几次时,我什至把一些ok和一些fail混合在一起。

我还在我的 linux 和 64bit mac ghc 上尝试过这段代码,它们都ok按我的预期输出。

我的一个朋友也在他的 32 位 mac ghc 上尝试过这个代码fail。他告诉我他对我的代码施了一些黑魔法,把一行代码改成了

 let x = decode $(C.pack. C.unpack) au :: Maybe AuctionInfo

那么输出是ok. 但是当我做同样的黑魔法时,输出仍然是fail.

我只是想确定这是我的错误还是 ghc 的错误,或者我该如何确定。

4

1 回答 1

2

我不确定该行为是否与此有关,但您绝对不应该使用Data.ByteString.Lazy.Char8,因为这仅适用于 8 位 ASCII 数据并且您的输入是 UTF-8。

尝试用

import qualified Data.ByteString.Lazy as BL

并用于BL.readFile读取数据(当然实际名称无关紧要,但BL它是惰性字节串包的惯用简写)。

请注意,通常您将Data.Text用于处理 unicode 文本,但在这种情况下,aesonAPI 需要二进制(即ByteString)表示并在内部处理 unicode 解码。

编辑:实际上现在我已经考虑了更多,我认为问题Char8毕竟不在于使用(尽管重点在于一般不将其用于 unicode 文本),因为您没有进行任何转换StringChar(预计C.pack . C.unpack实验会破坏所有多字节字符)。

于 2013-05-03T06:03:15.600 回答