本文介绍了与Aeson嵌套的JSON解析数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我试图为Aeson写一个 FromJSON
函数。
$ b $ {
total:1,
movies:[
{
ID:771315522,
title:哈利波特与魔法石(巫师系列),
海报:{
thumbnail:http:// content7.flixster.com/movie/11/16/66/11166609_mob.jpg,
profile:http://content7.flixster.com/movie/11/16/66/11166609_pro.jpg ,
详细:http://content7.flixster.com/movie/11/16/66/11166609_det.jpg,
original:http://content7.flixster。 com / movie / 11/16/66 / 11166609_ori.jpg
}
}
]
}
ADT: data Movie = Movie {id :: String,title :: String}
我的尝试:
instance FromJSON Movie其中
parseJSON(Object o)=做
电影< - parseJSON =<< (o。:movies):: Parser Array
v< - head $解码电影
return $ Movie< $>
(诉:电影>> =(。:id))*<
(v:movies>> =(。:title))
parseJSON _ = mzero
这给出无法与实际类型'Maybe a0'匹配的预期类型'Parser t0'在'head'的第一个参数中
正如你所看到的,我试图选择 Array
中的第一部电影,但我不介意获得电影列表(如果有几个在阵列中)。
如果你真的想从JSON数组中解析一个 Movie
,你可以这样做:
<$ p $
instance FromJSON Movie其中
parseJSON(Object o)= do
movieValue< - head< $> o。:电影
电影< $> movieValue。:id< *> movieValue。:title
parseJSON _ = mzero
但更安全的路线是通过 newtype
包装解析 [Movie]
main = print $ movieList< $>解码{\total \:1,\movies \:[{\id \:\771315522\,\title \:\哈利波特与魔法石(精灵集)\,\海报\:{\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}
实例FromJSON Movie其中
parseJSON(Object o)= Movie< $> o。:id< *> o。:title
parseJSON _ = mzero
I'm trying to write a FromJSON
function for Aeson.
The 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"
}
}
]
}
The ADT: data Movie = Movie {id::String, title::String}
My attempt:
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
This gives Couldn't match expected type 'Parser t0' with actual type 'Maybe a0' In the first argument of 'head'
.
As you can see, I'm trying to pick the first of the movies in the Array
, but I wouldn't mind getting a list of Movies either (in case there are several in the Array).
解决方案
If you really want to parse a single Movie
from a JSON array of movies, you can do something like this:
instance FromJSON Movie where
parseJSON (Object o) = do
movieValue <- head <$> o .: "movies"
Movie <$> movieValue .: "id" <*> movieValue .: "title"
parseJSON _ = mzero
But the safer route would be to parse a [Movie]
via newtype
wrapper:
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
这篇关于与Aeson嵌套的JSON解析数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!