用Haskell Aeson解析一个数组

csc*_*eid 9 json haskell aeson

我有一个JSON文档,看起来像:

{ "series": [[1,2], [2,3], [3,4]] }
Run Code Online (Sandbox Code Playgroud)

我想将其解析为一组数据类型:

data Series = Series [DataPoint]
data DataPoint = DataPoint Int Int  -- x and y
Run Code Online (Sandbox Code Playgroud)

我在尝试FromJSON为DataPoint 编写实例时遇到了很多问题.

instance FromJSON DataPoint where
  parseJSON (Array a) = ???
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用Lens来破坏DataPoint记录,但它不能编译:

case a ^.. values . _Integer of -}
  [x,y] -> DataPoint <$> x <*> y
  _     -> mzero
Run Code Online (Sandbox Code Playgroud)

这失败了这个错误(前两行甚至没有镜头技巧,只是试图创建一个DataPoint <$> 1 <*> 2):

Couldn't match type ‘aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
                       Integer’
              with ‘Integer’
Expected type: (aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
                  Integer
                -> Const
                     (Data.Monoid.Endo
                        [aeson-0.7.0.6:Data.Aeson.Types.Internal.Parse
                     (aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser I
               -> Value
               -> Const
                    (Data.Monoid.Endo
                       [aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
                    Value
  Actual type: (Integer
                -> Const
                     (Data.Monoid.Endo
                        [aeson-0.7.0.6:Data.Aeson.Types.Internal.Parse
                     Integer)
               -> Value
               -> Const
                    (Data.Monoid.Endo
                       [aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
                    Value
In the second argument of ‘(.)’, namely ‘_Integer’
In the second argument of ‘(^..)’, namely ‘values . _Integer’
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

有没有人有一个将值数组解析为更详细的结构的例子?

max*_*kin 15

Aeson有列表的实例,所以我认为没有必要处理向量.

{-# LANGUAGE LambdaCase #-}
import Data.Aeson

data Series = Series [DataPoint]
data DataPoint = DataPoint Int Int

instance FromJSON DataPoint where
  parseJSON jsn = do
    [x,y] <- parseJSON jsn
    return $ DataPoint x y

instance FromJSON Series where
  parseJSON = \case
    Object o -> (o .: "series") >>= fmap Series . parseJSON
    x -> fail $ "unexpected json: " ++ show x
Run Code Online (Sandbox Code Playgroud)