与Aeson嵌套的JSON解析数组 [英] Parse Array in nested JSON with Aeson

查看:200
本文介绍了与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解析数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆