我試圖解析一些書目數據,更具體地說,拉出每個項目的「主題」字段。該數據是JSON和看起來是這樣的:在Haskell中,如何解碼可能有兩種不同類型的JSON值?
{"rows": [
{"doc":{"sourceResource": {"subject": ["fiction", "horror"]}}},
{"doc":{"sourceResource": {"subject": "fantasy"}}}
]}
我可以拉出來「主題」,如果每一個條目是文本或[文字],但我難倒就如何適應兩種。這是我現在的程序狀態:
{-# LANGUAGE OverloadedStrings#-}
import Debug.Trace
import Data.Typeable
import Data.Aeson
import Data.Text
import Control.Applicative
import Control.Monad
import qualified Data.ByteString.Lazy as B
import Network.HTTP.Conduit (simpleHttp)
import qualified Data.HashMap.Strict as HM
import qualified Data.Map as Map
jsonFile :: FilePath
jsonFile = "bib.json"
getJSON :: IO B.ByteString
getJSON = B.readFile jsonFile
data Document = Document { rows :: [Row]}
deriving (Eq, Show)
data Row = SubjectList [Text]
| SubjectText Text
deriving (Eq, Show)
instance FromJSON Document where
parseJSON (Object o) = do
rows <- parseJSON =<< (o .: "rows")
return $ Document rows
parseJSON _ = mzero
instance FromJSON Row where
parseJSON (Object o) = do
item <- parseJSON =<< ((o .: "doc") >>=
(.: "sourceResource") >>=
(.: "subject"))
-- return $ SubjectText item
return $ SubjectList item
parseJSON _ = mzero
main :: IO()
main = do
d <- (decode <$> getJSON) :: IO (Maybe Document)
print d
任何幫助,將不勝感激。
編輯:
工作FromJSON行實例:
instance FromJSON Row where
parseJSON (Object o) =
(SubjectList <$> (parseJSON =<< val)) <|>
(SubjectText <$> (parseJSON =<< val))
where
val = ((o .: "doc") >>=
(.: "sourceResource") >>=
(.: "subject"))
parseJSON _ = mzero
我應該注意到,在這些類型的註釋表達並不是必需的,但只是爲了清晰起見。您應該在實際代碼中省略它們。 – icktoofay
非常感謝,這正是我需要的,但我不得不做出修改,即: (SubjectList <$> parseJSON = << val) <|> (SubjectText <$> parseJSON = << VAL) – reklak
@reklak:你應該能夠省略'= <<'如果你使用'do'符號並且在它之上有'val < - ...'而不是'let val = ...'。 – icktoofay