我正在尝试FromJSON为Aeson 编写一个函数.
JSON:
{
"total": 1,
"movies": [
{
"id": "771315522",
"title": "Harry Potter and the Philosophers Stone (Wizard's Collection)",
"posters": {
"thumbnail": "http://content7.flixster.com/movie/11/16/66/11166609_mob.jpg",
"profile": "http://content7.flixster.com/movie/11/16/66/11166609_pro.jpg",
"detailed": "http://content7.flixster.com/movie/11/16/66/11166609_det.jpg",
"original": "http://content7.flixster.com/movie/11/16/66/11166609_ori.jpg"
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
ADT: data Movie = Movie {id::String, title::String}
我的尝试:
instance FromJSON Movie where
parseJSON (Object o) = do
movies <- parseJSON =<< (o .: "movies") :: Parser Array
v <- head $ decode movies
return $ Movie <$>
(v .: "movies" >>= (.: "id") ) <*>
(v .: "movies" >>= (.: "title") )
parseJSON _ = mzero
Run Code Online (Sandbox Code Playgroud)
这给了Couldn't match expected type 'Parser t0' with actual type 'Maybe a0' In the first argument of 'head'.
正如你所看到的,我正在尝试选择第一部电影Array,但我不介意获得电影列表(如果数组中有几部电影).
Mik*_*aig 11
如果你真的想Movie从JSON电影数组中解析一个,你可以这样做:
instance FromJSON Movie where
parseJSON (Object o) = do
movieValue <- head <$> o .: "movies"
Movie <$> movieValue .: "id" <*> movieValue .: "title"
parseJSON _ = mzero
Run Code Online (Sandbox Code Playgroud)
但更安全的方法是解析一个[Movie]via newtype包装器:
main = print $ movieList <$> decode "{\"total\":1,\"movies\":[ {\"id\":\"771315522\",\"title\":\"Harry Potter and the Philosophers Stone (Wizard's Collection)\",\"posters\":{\"thumbnail\":\"http://content7.flixster.com/movie/11/16/66/11166609_mob.jpg\",\"profile\":\"http://content7.flixster.com/movie/11/16/66/11166609_pro.jpg\",\"detailed\":\"http://content7.flixster.com/movie/11/16/66/11166609_det.jpg\",\"original\":\"http://content7.flixster.com/movie/11/16/66/11166609_ori.jpg\"}}]}"
newtype MovieList = MovieList {movieList :: [Movie]}
instance FromJSON MovieList where
parseJSON (Object o) = MovieList <$> o .: "movies"
parseJSON _ = mzero
data Movie = Movie {id :: String, title :: String}
instance FromJSON Movie where
parseJSON (Object o) = Movie <$> o .: "id" <*> o .: "title"
parseJSON _ = mzero
Run Code Online (Sandbox Code Playgroud)
通常最简单的方法是将ADT和实例的结构与JSON的结构相匹配.
在这里,我添加了一个newtype MovieList来处理最外面的对象,这样实例Movie只需要处理一个电影.这也可以通过FromJSON列表实例免费为您提供多部电影.
data Movie = Movie { id :: String, title :: String }
newtype MovieList = MovieList [Movie]
instance FromJSON MovieList where
parseJSON (Object o) =
MovieList <$> (o .: "movies")
parseJSON _ = mzero
instance FromJSON Movie where
parseJSON (Object o) =
Movie <$> (o .: "id")
<*> (o .: "title")
parseJSON _ = mzero
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3072 次 |
| 最近记录: |