Haskell Aeson 处理缺失数据

标签 haskell aeson

我有一个(有效)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/

相关文章:

json - Haskell,Aeson - 有没有更好的方法从 USDA 数据库获取我需要的信息?

haskell - 在 haskell 中,结合 "case"和 ">>="

memory-management - 如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?

haskell - 在数据类型构造函数中使用类

Haskell 类型同义词

haskell - 如何做 map 也许使用镜头

parsing - 如何使用 Haskell 解析中缀而不是前缀?

json - 将选项对象解析为选项列表

haskell - 让 ToJSON 使用 Show Instance

json - Aeson:解析枚举数据类型