如何用 aeson 将数组解析为元组?
How to parse array into tuple with aeson?
如果我有一个数组["addTask", {"id": "1", "description": "d", "dependsOn": [], "dependentTasks": []}]
。
data Task = Task
{ id :: String
, description :: String
, dependsOn :: [String]
, dependentTasks :: [String]
} deriving (Eq, Show, Generic, ToJSON, FromJSON)
type Change = Storage -> Storage
addTask :: Task -> Change
addTask (Task id desc dep dept) = insert id (Task id desc dep dept)
我如何创建一个解析器来从中生成 addTask?
instance FromJSON (Storage -> Storage) where
parseJSON (Array v) = do
name <- parseJSON $ v V.! 0 :: Just String
task <- parseJSON $ v V.! 1 :: Just Task
return (addTask task)
这是我目前的尝试,但没有用。
我会继续将 Array 解析为元组 (String,Task)
然后使用简单的模式匹配,如果您使用 OverloadedStrings
则可能需要指定 "addTask" 的类型,这可以用 ScopedTypeVariables
完成(只需将它添加到 .. :: (String, Task) <- parse..
的左侧)。
instance FromJSON (Storage -> Storage) where
parseJSON v = do ("addTask",t) <- parseJSON v
return $ addTask t
注意:我没有编译或测试这段代码
编辑
使用 alternative 非常简单,您只需定义两个解析器并将它们组合起来
instance FromJSON (Storage -> Storage) where
parseJSON v = let addP = do ("addTask",t) <- parseJSON v
return $ addTask t
rmP = do ("rmTask",n) <- parseJSON v
return $ rmTask n
in addP <|> rmP
我假设 rmTask :: Int -> Change
否则你总是可以 case
在元组的第一个元素上。
如果我有一个数组["addTask", {"id": "1", "description": "d", "dependsOn": [], "dependentTasks": []}]
。
data Task = Task
{ id :: String
, description :: String
, dependsOn :: [String]
, dependentTasks :: [String]
} deriving (Eq, Show, Generic, ToJSON, FromJSON)
type Change = Storage -> Storage
addTask :: Task -> Change
addTask (Task id desc dep dept) = insert id (Task id desc dep dept)
我如何创建一个解析器来从中生成 addTask?
instance FromJSON (Storage -> Storage) where
parseJSON (Array v) = do
name <- parseJSON $ v V.! 0 :: Just String
task <- parseJSON $ v V.! 1 :: Just Task
return (addTask task)
这是我目前的尝试,但没有用。
我会继续将 Array 解析为元组 (String,Task)
然后使用简单的模式匹配,如果您使用 OverloadedStrings
则可能需要指定 "addTask" 的类型,这可以用 ScopedTypeVariables
完成(只需将它添加到 .. :: (String, Task) <- parse..
的左侧)。
instance FromJSON (Storage -> Storage) where
parseJSON v = do ("addTask",t) <- parseJSON v
return $ addTask t
注意:我没有编译或测试这段代码
编辑
使用 alternative 非常简单,您只需定义两个解析器并将它们组合起来
instance FromJSON (Storage -> Storage) where
parseJSON v = let addP = do ("addTask",t) <- parseJSON v
return $ addTask t
rmP = do ("rmTask",n) <- parseJSON v
return $ rmTask n
in addP <|> rmP
我假设 rmTask :: Int -> Change
否则你总是可以 case
在元组的第一个元素上。