这是我在Stack Overflow上的第一篇文章,我对Haskell和编程/ Web开发一般都是新手。我正在使用它来尝试将一些JSON解析为ADT类型。
以下是我想尝试解析的JSON部分:
{"resource":"teamgamelog",
"parameters":{"TeamID":1610612747,"LeagueID":null,"Season":"2015-16","SeasonType":"Regular Season","DateFrom":null,"DateTo":null},
"resultSets":[
{"name":"TeamGameLog",
"headers":["Team_ID","Game_ID","GAME_DATE","MATCHUP","WL","W","L","W_PCT","MIN","FGM","FGA","FG_PCT","FG3M","FG3A","FG3_PCT","FTM","FTA","FT_PCT","OREB","DREB","REB","AST","STL","BLK","TOV","PF","PTS"],
"rowSet": [ [1610612747,"0021501228","APR 13, 2016","LAL vs. UTA","W",17,65,0.207,240,41,85,0.482,6,25,0.240,13,15,0.867,8,39,47,19,6,3,13,17,101]
,[1610612747,"0021501209","APR 11, 2016","LAL @ OKC","L",16,65,0.198,240,23,81,0.284,7,31,0.226,26,30,0.867,10,38,48,15,8,1,15,20,79]
,[1610612747,"0021501195","APR 10, 2016","LAL @ HOU","L",16,64,0.2,240,41,83,0.494,12,28,0.429,16,19,0.842,7,33,40,25,10,3,18,15,110]
.
.
.
]
}
}
我想要完成的工作最后是[GameResult]
,其中每个GameResult
都来自JSON "rowSet"
密钥中的嵌套数组:
data GameResult = GameResult { team_ID :: Int
, game_ID :: String
, game_date :: String
, matchup :: String
, wl :: Char
, w :: Int
, l :: Int
, w_pct :: Float
, min :: Int
, fgm :: Int
, fga :: Int
, fg_pct :: Float
, fg3m :: Int
, fg3a :: Int
, fg3_pct :: Float
, ftm :: Int
, fta :: Int
, ft_pct :: Float
, oreb :: Int
, dreb :: Int
, reb :: Int
, ast :: Int
, stl :: Int
, blk :: Int
, tov :: Int
, pf :: Int
, pts :: Int
} deriving (Show, Eq, Ord, Read)
到目前为止,我有这个:
module Main where
import Data.Aeson
import Network.HTTP.Conduit (simpleHttp)
data RowSet = ResultSet [GameResult] deriving (Show, Eq, Read)
data ResultSets = ResultSets [RowSet] deriving (Show, Eq, Read)
instance FromJSON ResultSets where
parseJSON (Object o) = ResultSets <$> (o .: "resultSets")
instance FromJSON RowSetSet where
parseJSON (Object o) = RowSet <$> (o .: "rowSet")
jsonURL :: String
jsonURL = "http://stats.nba.com/stats/teamgamelog/?Season=2015-16&SeasonType=Regular%20Season&TeamID=1610612747"
getJSON :: IO B.ByteString
getJSON = simpleHttp jsonURL
main :: IO ()
main = do
d <- (eitherDecode <$> getJSON) :: IO (Either String (Maybe ResultSets))
case d of
Left err -> putStrLn err
Right ps -> putStrLn (show ps)
不确定这是否应该是我应该去的方向,但我想到了一个冗长的模式匹配:
instance FromJSON GameResult where
parseJSON arr = do
[a,b,c,...x,y,z] <- parseJSON arr
GameResult <$> a <*> b <*> c <*> ...
当然,我在尝试编译时遇到了一些错误:
Couldn't match type ‘Int’ with ‘Float’
Expected type: Parser Float
Actual type: Parser Int
In the second argument of ‘(<*>)’, namely ‘l’
In the first argument of ‘(<*>)’, namely
‘GameResult <$> a <*> b <*> c <*> d <*> e <*> f <*> g <*> h <*> i
<*> j
<*> k
<*> l’
In the first argument of ‘(<*>)’, namely
‘GameResult <$> a <*> b <*> c <*> d <*> e <*> f <*> g <*> h <*> i
<*> j
<*> k
<*> l
<*> m’
我在控制台中总共有8个错误。
我很感激我能得到的任何帮助。如果这篇文章有点冗长而且代码不好,我很抱歉。
编辑:事实证明我已经解决了我的问题。感谢jonathan-portorreal和epsilonhalbe,我再次查看了我的类型,并查看了Lens包中的一些想法。我最终在我的do
实例中使用了FromJSON GameResult
块,但我仍然遇到类型问题,因为事实证明我使用w
和l
作为某些字段名称GameResult
ADT及其之外。
instance FromJSON GameResult where
parseJSON arr = do
[a,b,c,d,...,l,...,w,x,y,z] <- parseJSON arr
team_ID <- a
game_ID <- b
game_date <- c
matchup <- d
wl <- e
w <- f
l <- g
...
<- l
...
<- w
我绝对会清理它,一旦我更熟悉基础知识,可能会使用Lens包。