Aeson解析成多个构造函数
Aeson parsing into multiple constructors
我正在尝试解析 JSON 以生成具有多个构造函数的类型。挑战在于类型以包含所需数据的键的名称进行编码。理论上我可以使用一堆 .:?
调用然后检查是否给定密钥 returns Just
但我认为必须有更好的方法。我看了 asum
但这对我没有太大帮助(可能是因为我不熟悉它)。
import Data.Aeson
import Data.Time.Clock
data Request = Req1 { id :: String, properties :: Value }
| Req2 { id :: String, properties :: Value }
| Req3 { id :: String, time :: UTCTime }
instance FromJSON Request where
parseJSON = withObject "message" $ \o ->
-- ???
请求示例:
{"req1": {"id": "345", "p1": "v1", "p2": "v2"}}
{"req2": {"id": "654", "p3", "v3"}}
{"req3": {"id": "876", "time": 1234567890}}
手动检查对象的方法如下:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Time.Clock
import qualified Data.HashMap.Strict as H
import Control.Monad
type Val = Int
data Request = Req1 { id :: String, properties :: Val }
| Req2 { id :: String, properties :: Val }
| Req3 { id :: String, time :: UTCTime }
instance FromJSON Request where
parseJSON (Object v) =
case H.lookup "req1" v of
Just (Object h) -> Req1 <$> h .: "id" <*> h .: "properties"
Nothing ->
case H.lookup "req2" v of
Just (Object h) -> Req2 <$> h .: "id" <*> h .: "properies"
Nothing ->
case H.lookup "req3" v of
Just (Object h) -> Req3 <$> h .: "id" <*> h .: "time"
Nothing -> mzero
如果键 req1
存在,它将假定它是一个 Req1 值;否则,如果键 req2
存在,它将尝试将其解析为 Req2 值;等等 req3
。如果 none 个键存在,它将失败。
除了 mzero
,您还可以使用 fail "..."
来显示自定义错误消息。
我正在尝试解析 JSON 以生成具有多个构造函数的类型。挑战在于类型以包含所需数据的键的名称进行编码。理论上我可以使用一堆 .:?
调用然后检查是否给定密钥 returns Just
但我认为必须有更好的方法。我看了 asum
但这对我没有太大帮助(可能是因为我不熟悉它)。
import Data.Aeson
import Data.Time.Clock
data Request = Req1 { id :: String, properties :: Value }
| Req2 { id :: String, properties :: Value }
| Req3 { id :: String, time :: UTCTime }
instance FromJSON Request where
parseJSON = withObject "message" $ \o ->
-- ???
请求示例:
{"req1": {"id": "345", "p1": "v1", "p2": "v2"}}
{"req2": {"id": "654", "p3", "v3"}}
{"req3": {"id": "876", "time": 1234567890}}
手动检查对象的方法如下:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Time.Clock
import qualified Data.HashMap.Strict as H
import Control.Monad
type Val = Int
data Request = Req1 { id :: String, properties :: Val }
| Req2 { id :: String, properties :: Val }
| Req3 { id :: String, time :: UTCTime }
instance FromJSON Request where
parseJSON (Object v) =
case H.lookup "req1" v of
Just (Object h) -> Req1 <$> h .: "id" <*> h .: "properties"
Nothing ->
case H.lookup "req2" v of
Just (Object h) -> Req2 <$> h .: "id" <*> h .: "properies"
Nothing ->
case H.lookup "req3" v of
Just (Object h) -> Req3 <$> h .: "id" <*> h .: "time"
Nothing -> mzero
如果键 req1
存在,它将假定它是一个 Req1 值;否则,如果键 req2
存在,它将尝试将其解析为 Req2 值;等等 req3
。如果 none 个键存在,它将失败。
除了 mzero
,您还可以使用 fail "..."
来显示自定义错误消息。