我向服务器发出了大量此类请求,返回JSON:
MyJsonData = MyJsonData { field1 :: String, field2 :: String }
d <- (Aeson.eitherDecode <$> simpleHttp "https://someUrl.com") :: IO (Either String MyJsonData)
print d
MyJsonData2 = MyJsonData2 { field12 :: String, field22 :: String }
d2 <- (Aeson.eitherDecode <$> simpleHttp "https://someUrl2.com") :: IO (Either String MyJsonData2)
print d2
当然,就JSON表示而言,所有服务器都返回相似但不准确的数据。我只需要从这几个字段中获取值,我不需要它们。我希望能够做到以下几点:
-- not valid Haskell code!
(d1, d2) <- (Aeson.eitherDecode <$> simpleHttp "https://someUrl.com") :: IO (Either String (_ _ _ fieldINeed _ _ fieldIneed2))
print d1
print d2
(d3, d4) <- (Aeson.eitherDecode <$> simpleHttp "https://someUrl2.com") :: IO (Either String (_ _ fieldINeed3 fieldIneed4 _ _ _))
print d3
print d4
或类似的东西。这个想法是摆脱定义data
S MyJsonData
,MyJsonData2
等的必要性。这可能吗?
答案 0 :(得分:2)
这样的事情应该有效:
output <- Aeson.eitherDecode rawData :: IO (Either String Aeson.Value)
case output of
Right jsonValue -> case jsonValue of
(Aeson.Object jsonObject) -> case (HashMap.lookup "someKey" jsonObject, HashMap.lookup "anotherKey" jsonObject) of
(Just val, Just val2) -> -- Your code here
_ -> error "Couldn't get both keys"
_ -> error "Unexpected JSON"
Left errorMsg -> error $ "Error in parsing: " ++ errorMsg
基本上,JSON对象只是一个HashMap,你可以操作,而JSON数组只是vector。
如果您有一堆密钥,只需map
HashMap.lookup
一组密钥,然后在列表中运行sequence
即可获得所需内容。
case (sequence $ map (\k -> HashMap.lookup k jsonObject) ["key1", "key2", "key3"]) of
Just x -> -- Your code here
Nothing -> error "Some key missing"
答案 1 :(得分:1)
请注意,Data.Aeson.Value
是FromJSON
的实例。因此,您可以解码对Value
的响应,然后仅提取您需要的内容。
例如
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Aeson.Types
import Control.Monad
parser1 :: Value -> Parser (String, String)
parser1 (Object o) = do
str1 <- o .: "str1"
str2 <- o .: "str2"
return (str1, str2)
parser1 _ = mzero
parser2 :: Value -> Parser (String, String)
parser2 (Object o) = do
str1 <- o .: "string1"
str2 <- o .: "string2"
return (str1, str2)
parser2 _ = mzero
main :: IO ()
main = do
let json1 = object [
"str1" .= ("world" :: String),
"str2" .= ("12" :: String),
"other" .= (12.5 :: Float)
]
let json2 = object [
"string1" .= ("world" :: String),
"string2" .= ("12" :: String),
"other" .= (12.5 :: Float)
]
print $ parseEither parser1 json1
print $ parseEither parser2 json2
ADD: 您可以使用字段名称参数化解析器:
parser :: (Text, Text) -> Value -> Parser (String, String)
parser (f1, f2) (Object o) = do
str1 <- o .: f1
str2 <- o .: f2
return (str1, str2)
parser _ _ = mzero
...
print $ parseEither (parser ("str1", "str2")) json1
print $ parseEither (parser ("string1", "string2")) json2