我有一个(有效)json 编码数组,其中数据丢失或格式错误。我希望 Aeson 将其转换为 Maybe [Maybe Point]
并具有 Nothing
,其中数组元素不是有效的 Point
。
import Data.Aeson
decode "[1,2,3,4,null,\"hello\"]" :: (Maybe [Maybe Int])
=> Nothing
但我更愿意让它评估为
=> Just [Just 1, Just 2, Just 3, Just 4, Nothing, Nothing]
如果 Aeson 无法做到这一点,是否还有其他库可以做到这一点?
请注意,实际对象比简单的整数复杂得多,因此字符串操作不是可行的解决方案。
最佳答案
我们可以围绕Maybe
创建一个新类型,它在解析失败时不会失败,而是以Nothing
成功:
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
import Data.Aeson
import Data.Coerce
import Control.Applicative
import Control.Monad
newtype Maybe' a = Maybe' (Maybe a) deriving
(Eq, Ord, Show, Functor, Applicative, Monad, Alternative, MonadPlus)
instance FromJSON a => FromJSON (Maybe' a) where
parseJSON v = do
case fromJSON v :: Result a of
Success a -> pure (Maybe' $ Just a)
_ -> pure (Maybe' $ Nothing)
现在我们可以用 Maybe'
包装类型以获得所需的行为:
> decode "[4, 5, \"foo\", \"bar\"]" :: Maybe [Maybe' Int]
Just [Maybe' (Just 4),Maybe' (Just 5),Maybe' Nothing,Maybe' Nothing]
但是,之后我们很有可能希望使用常规的Maybe
值。 Data.Coerce
在这里很方便,因为它允许我们将所有 Maybe'
-s 强制转换为 Maybe
-s,无论它们在结果类型中的位置:
> coerce (decode "[[[], 3], [4, 5]]" :: Maybe [(Maybe' Int, Int)]) :: Maybe [(Maybe Int, Int)]
Just [(Nothing,3),(Just 4,5)]
关于Haskell Aeson 处理缺失数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33912046/