【发布时间】:2015-04-13 15:33:02
【问题描述】:
我一直在针对基于 JSON 的 API 开发一个小型库。该库使用“选项”对象,即一系列指定高级行为的键值对:
{
"id": 1234
...
"options": {
"notify_no_data": True,
"no_data_timeframe": 20,
"notify_audit": False,
"silenced": {"*" :1428937807}
}
}
我在 Haskell 中使用选项列表来表示选项概念:
data Option = NotifyNoData NominalDiffTime -- notify after xyz
| NotifyAudit -- notify on changes
| Silenced (Maybe UTCTime) -- silence all notifications ("*") until xyz (or indefinitely)
newtype Options = Options [Option]
实现toJSON 很简单;我为Option 类型实例化了toJSON,然后将它们用作Options 类型的助手。
instance ToJSON Option where
toJSON (Silenced mtime) =
Object $ Data.HashMap.fromList [("silenced", mapping)]
where stamp = maybe Null (jsonTime . floor . utcTimeToPOSIXSeconds) mtime
mapping = Object $ Data.HashMap.singleton "*" stamp
toJSON (NotifyNoData difftime) =
Object $ Data.HashMap.fromList [("notify_no_data", Bool True)
,("no_data_timeframe", stamp)]
where stamp = jsonTime $ floor (difftime / 60)
toJSON NotifyAudit =
Object $ Data.HashMap.fromList [("notify_audit", Bool True)]
instance ToJSON Options where
toJSON (Options options) = Object $ Data.HashMap.unions $ reverse $ (opts:) $ map ((\(Object o) -> o) . toJSON) options
where opts = Data.HashMap.fromList [("silenced", Object Data.HashMap.empty)
,("notify_no_data", Bool False)
,("notify_audit", Bool False)]
我遇到的问题在于Options 的fromJSON 实现。我之前看到的所有用例都为数据表示映射提供了一个相当简单的 json-object-representation。我需要做的是将对象转换为选项对象到数据(选项)表示的列表。例如,我在开始时给出的“选项”下的示例 JSON 必须变为:
Options [NotifyNoData 20, Silenced (Just (posixSecondsToUTCTime 1428937807))]
FromJSON 需要实现parseJSON :: FromJSON a => Value -> Parser a。我无法理解如何使用 API 提供的这个可选对象结构来构建解析器。是否有将 JSON 对象解析为这样的列表的标准方法?可能是我没有完全理解 Parser 类型类。
【问题讨论】:
标签: json parsing haskell aeson