我想解析一个JSON对象并使用给定的name
和args
我正在使用Aeson,现在我仍然坚持将"args":[{"a": "b"}]
转换为[(String, String)]
。
提前感谢!
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import Data.Aeson
data JSONEvent = JSONEvent [(String, String)] (Maybe String) deriving Show
instance FromJSON JSONEvent where
parseJSON j = do
o <- parseJSON j
name <- o .:? "name"
args <- o .:? "args" .!= []
return $ JSONEvent args name
let decodedEvent = decode "{\"name\":\"edwald\",\"args\":[{\"a\": \"b\"}]}" :: Maybe JSONEvent
答案 0 :(得分:3)
我不是aeson专家,但如果你有Object o
,那么 o 只是HashMap Text Value
;您可以使用Data.HashMap.Lazy.toList将其转换为[(Text, Value)]
,并Data.Text.unpack将Text
转换为String
s。
所以,大概你可以写:
import Control.Arrow
import Control.Applicative
import qualified Data.Text as T
import qualified Data.Foldable as F
import qualified Data.HashMap.Lazy as HM
import Data.Aeson
instance FromJSON JSONEvent where
parseJSON j = do
o <- parseJSON j
name <- o .:? "name"
Object m <- o .:? "args" .!= []
args <- map (first T.unpack) . HM.toList <$> F.mapM parseJSON m
return $ JSONEvent args name
答案 1 :(得分:3)
这是基于ehird的例子的更详细的例子。请注意,调用parseJSON时的显式输入是不必要的,但我发现它们对于文档和调试非常有用。此外,我不确定您的意图,但args
具有多个值,我只需将所有args
连接在一起,如下所示:
*Main> decodedEvent2
Just (JSONEvent [("a","b"),("c","d")] (Just "edwald"))
*Main> decodedEvent3
Just (JSONEvent [("a","b"),("c","d")] (Just "edwald"))
以下是代码:
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import qualified Data.Text as T
import qualified Data.Foldable as F
import qualified Data.HashMap.Lazy as HM
import qualified Data.Vector as V
import Data.Aeson
import qualified Data.Attoparsec as P
import Data.Aeson.Types (Parser)
import qualified Data.Aeson.Types as DAT
import qualified Data.String as S
data JSONEvent = JSONEvent [(String, String)] (Maybe String) deriving Show
instance FromJSON JSONEvent where
parseJSON = parseJSONEvent
decodedEvent = decode "{\"name\":\"edwald\",\"args\":[{\"a\": \"b\"}]}" :: Maybe JSONEvent
decodedEvent2 = decode "{\"name\":\"edwald\",\"args\":[{\"a\": \"b\"}, {\"c\": \"d\"}]}" :: Maybe JSONEvent
decodedEvent3 = decode "{\"name\":\"edwald\",\"args\":[{\"a\": \"b\", \"c\": \"d\"}]}" :: Maybe JSONEvent
emptyAesonArray :: Value
emptyAesonArray = Array $ V.fromList []
parseJSONEvent :: Value -> Parser JSONEvent
parseJSONEvent v =
case v of
Object o -> do
name <- o .:? "name"
argsJSON <- o .:? "args" .!= emptyAesonArray
case argsJSON of
Array m -> do
parsedList <- V.toList <$> V.mapM (parseJSON :: Value -> Parser (HM.HashMap T.Text Value)) m
let parsedCatList = concatMap HM.toList parsedList
args <- mapM (\(key, value) -> (,) <$> (return (T.unpack key)) <*> (parseJSON :: Value -> Parser String) value) parsedCatList
return $ JSONEvent args name
_ -> fail ((show argsJSON) ++ " is not an Array.")
_ -> fail ((show v) ++ " is not an Object.")
-- Useful for debugging aeson parsers
decodeWith :: (Value -> Parser b) -> String -> Either String b
decodeWith p s = do
value <- P.eitherResult $ (P.parse json . S.fromString) s
DAT.parseEither p value