haskell - Aeson 具有数组的数组,其中一些是空的

标签 haskell aeson

我有不幸的数据需要处理:

{ "name": "foo"
, "data": [ []
          , ["a", "b", "c", 1]
          , ["d", "e", "f", 2] ] }

数据条目可以是空数组,也可以是大小为 4 的数组。

我想解析为:

data ResultRow = ResultRow Text Text Text Int deriving (Show, Generic)

data ResultSet =
  ResultSet { f_name :: Text
            , f_data :: [Maybe ResultRow] } deriving (Show, Generic)

但是以下内容不接受空数组:

customOptions = defaultOptions { fieldLabelModifier = drop 2 }

instance FromJSON ResultRow where
  parseJSON = genericParseJSON customOptions
instance FromJSON ResultSet where
  parseJSON = genericParseJSON customOptions

错误信息是:

Left "Error in $[1].data[0]: When expecting a product of 4 values, encountered an Array of 0 elements instead"

我还尝试在 [Maybe ResultRow] 周围放置额外的类型,并将子数组转换为列表并在 [] 上进行模式匹配,然后调度将非空情况传递给 ResultRow 解析器,但我根本无法编译它并迷失在错误消息中。

理想情况下,我希望有某种方法可以跳过空数组,因为它们只是数据中的噪音。我无法控制数据的生产者。

最佳答案

dsvensson一样,我很困惑这不能“直接工作”开箱即用,因为 [a]Maybe aFromJSONa 时的实例是。由于我已经在这方面花费了太多时间,因此我无法提供解释,但我可以提供解决方法。希望有了解的人可以给出更好的答案。

而不是定义f_data作为[Maybe ResultRow] ,您可以定义 newtype包裹 Maybe ResultRow :

newtype MaybeResultRow = MaybeResultRow (Maybe ResultRow) deriving (Show, Generic)

你可以给这个类型特殊FromJSON行为:

instance FromJSON MaybeResultRow where
  parseJSON v =
    case fromJSON v of
      Success rr -> return $ MaybeResultRow $ Just rr
      _          -> return $ MaybeResultRow Nothing

这显然意味着 ResultSet 的更改:

data ResultSet =
  ResultSet { f_name :: Text
            , f_data :: [MaybeResultRow] } deriving (Show, Generic)

为了测试,我定义了这个 JSON 文档:

myJson :: ByteString
myJson =
  "{\
     \\"name\": \"foo\",\
     \\"data\": [\
        \[],\
        \[\"a\", \"b\", \"c\", 1],\
        \[\"d\", \"e\", \"f\", 2]\
     \]\
   \}"

将其全部加载到 GHCi 中,看起来它正在工作:

*Lib Lib> decode myJson :: Maybe ResultSet
Just (ResultSet {
          f_name = "foo"
        , f_data = [
                     MaybeResultRow Nothing,
                     MaybeResultRow (Just (ResultRow "a" "b" "c" 1)),
                     MaybeResultRow (Just (ResultRow "d" "e" "f" 2))]})

在这里,我冒昧地对 GHCi 的输出进行了格式化,以增强可读性。

我相信您可以弄清楚如何打开和过滤 MaybeResultRow 的列表值(value)观...

我偷了使用fromJSON的解决方案并匹配Success来自this answer .

关于haskell - Aeson 具有数组的数组,其中一些是空的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46780677/

相关文章:

haskell - Haskell 中通过 unsafePerformIO 的全局变量

Haskell Aeson 处理缺失数据

haskell - 爱生 : generics with default values

haskell - 在 json 解析中使用文件名 (Haskell Aeson)

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

haskell - 是否可以在 Haskell 中使用可调用对象定义类型?

haskell - 该函数的正确类型声明是什么?

haskell - 为什么 `:type` 有时会显示 `a` 而有时会显示 `t` ?

haskell - 将元素列表折叠为元素集合

haskell - 是否可以从数据类型中普遍删除函数类型,以允许deriveJSON?