ByteString到Json格式

时间:2018-12-02 08:42:23

标签: haskell

我正在构建一个调用API的连接器,并以json格式返回一些数据。我收到休息响应时的数据类型为ByteString,所以 使用Scotty http服务器渲染后,我将使用aeson。查看aeson文档,我看到了:

instance ToJSON ByteString
instance FromJSON ByteString

但是自not instance for (Generic ByteString)

开始就没有编译
responseMovie :: ActionM ()
responseMovie = do movie <- extractUriParam "movie"
                   response <- liftAndCatchIO $ simpleGetRequest $ searchMovieQuery movie
                   json (show response)

但是我渲染的格式是字符串。

知道我在做什么错吗?

"\"{\\\"Title\\\":\\\"Mad Max\\\",\\\"Year\\\":\\\"1979\\\",\\\"Rated\\\":\\\"R\\\",\\\"Released\\\":\\\"21 Mar 1980\\\",\\\"Runtime\\\":\\\"88 min\\\",\\\"Genre\\\":\\\"Action, Adventure, Sci-Fi, Thriller\\\",\\\"Director\\\":\\\"George Miller\\\",\\\"Writer\\\":\\\"James McCausland (screenplay), George Miller (screenplay), George Miller (original story), Byron Kennedy (original story)\\\",\\\"Actors\\\":\\\"Mel Gibson, Joanne Samuel, Hugh Keays-Byrne, Steve Bisley\\\",\\\"Plot\\\":\\\"In a self-destructing world, a vengeful Australian policeman sets out to stop a violent motorcycle gang.\\\",\\\"Language\\\":\\\"English\\\",\\\"Country\\\":\\\"Australia\\\",\\\"Awards\\\":\\\"4 wins & 7 nominations.\\\",\\\"Poster\\\":\\\"https://m.media-amazon.com/images/M/MV5BMTM4Mjg5ODEzMV5BMl5BanBnXkFtZTcwMDc3NDk0NA@@._V1_SX300.jpg\\\",\\\"Ratings\\\":[{\\\"Source\\\":\\\"Internet Movie Database\\\",\\\"Value\\\":\\\"7.0/10\\\"},{\\\"Source\\\":\\\"Rotten Tomatoes\\\",\\\"Value\\\":\\\"90%\\\"},{\\\"Source\\\":\\\"Metacritic\\\",\\\"Value\\\":\\\"73/100\\\"}],\\\"Metascore\\\":\\\"73\\\",\\\"imdbRating\\\":\\\"7.0\\\",\\\"imdbVotes\\\":\\\"172,382\\\",\\\"imdbID\\\":\\\"tt0079501\\\",\\\"Type\\\":\\\"movie\\\",\\\"DVD\\\":\\\"19 Nov 1997\\\",\\\"BoxOffice\\\":\\\"N/A\\\",\\\"Production\\\":\\\"s\\\",\\\"Website\\\":\\\"N/A\\\",\\\"Response\\\":\\\"True\\\"}\""

以防在这里我粘贴程序

searchMovieQuery :: String -> String
searchMovieQuery movie = "http://www.omdbapi.com/?apikey="++ omdbKey ++ "&t=" ++ movie

startServer :: IO ()
startServer = do
              print ("Starting Omdb server at port: " ++ show port)
              scotty port routes

routes ::  ScottyM()
routes = do get "/movie/:movie" responseMovie

responseMovie :: ActionM ()
responseMovie = do movie <- extractUriParam "movie"
                   liftAndCatchIO $ print ("Finding movie" ++ movie)
                   bsResponse <- liftAndCatchIO $ simpleGetRequest $ searchMovieQuery movie
                   liftAndCatchIO $ print ("Response:" ++ (show bsResponse))
                   txtResponse <- liftAndCatchIO $ transform bsResponse
                   json txtResponse

extractUriParam :: LazyText.Text -> ActionM String
extractUriParam param = Web.Scotty.param param


transform :: Inter.ByteString -> IO LazyText.Text
transform bs = do txtResponse <- case (decode bs) of
                                      Just value -> return value
                                      Nothing -> return (LazyText.pack $ "Nothing to share:" ++ (show bs))
                  return txtResponse


simpleGetRequest :: String -> IO ByteString
simpleGetRequest uri = do
                    manager <- newManager defaultManagerSettings
                    request <- parseRequest uri
                    response <- makeRequest manager request
                    return $ responseBody response

makeRequest :: Manager -> Request -> IO (Response ByteString)
makeRequest manager request =  httpLbs request manager

正如您提到的,我使用解码将ByteString转换为Text。 但是,现在在解码B yteString -> Text中,Maybe中的数据总是在Nothing中,甚至有数据。

1 个答案:

答案 0 :(得分:2)

如果我正确理解了您的问题:

  • 您知道从ByteString返回的simpleGetRequest包含JSON
  • 您不在乎该JSON的具体内容
  • 您要将ByteString传递给json from Scotty

aeson提供了一种类型Value来表示JSON,但没有提供有关什么字段的任何详细信息。因此,一种选择是:

let response = case decode bsResponse of
    Nothing -> Null
    Just value -> value
json response

其中NullValue的构造函数之一。当然,在Nothing情况下,您还可以做出其他选择。

另一种方法是使用raw :: ByteString -> ActionM () from Scotty

,它保存了JSON解析然后重新编码的往返过程。

您在帖子顶部提到的定义GenericToJSON的{​​{1}}方法适用于用户定义的类型,而该类型的每个字段都已经具有{已定义{1}} / FromJSONToJSON不是那样的。通常,FromJSON可以包含任何字节。通常在同一程序的不同部分使用它来表示不同类型的值,这些值在JSON中应以不同的方式表示。因此,我们必须明确说明我们期望什么以及如何对其进行编码。