我正在构建一个调用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
中,甚至有数据。
答案 0 :(得分:2)
如果我正确理解了您的问题:
ByteString
返回的simpleGetRequest
包含JSON ByteString
传递给json
from Scotty aeson
提供了一种类型Value
来表示JSON,但没有提供有关什么字段的任何详细信息。因此,一种选择是:
let response = case decode bsResponse of
Nothing -> Null
Just value -> value
json response
其中Null
是Value
的构造函数之一。当然,在Nothing
情况下,您还可以做出其他选择。
另一种方法是使用raw :: ByteString -> ActionM ()
from Scotty
您在帖子顶部提到的定义Generic
和ToJSON
的{{1}}方法适用于用户定义的类型,而该类型的每个字段都已经具有{已定义{1}} / FromJSON
。 ToJSON
不是那样的。通常,FromJSON
可以包含任何字节。通常在同一程序的不同部分使用它来表示不同类型的值,这些值在JSON中应以不同的方式表示。因此,我们必须明确说明我们期望什么以及如何对其进行编码。