Json 如何使用Haskell Aeson解析数组

Json 如何使用Haskell Aeson解析数组,json,haskell,aeson,Json,Haskell,Aeson,我有一个JSON文档,看起来像: { "series": [[1,2], [2,3], [3,4]] } 我想将其解析为一组数据类型: data Series = Series [DataPoint] data DataPoint = DataPoint Int Int -- x and y 我在为DataPoint编写FromJSON实例时遇到了很多问题 instance FromJSON DataPoint where parseJSON (Array a) = ??? 我尝试使

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

{ "series": [[1,2], [2,3], [3,4]] }
我想将其解析为一组数据类型:

data Series = Series [DataPoint]
data DataPoint = DataPoint Int Int  -- x and y
我在为DataPoint编写
FromJSON
实例时遇到了很多问题

instance FromJSON DataPoint where
  parseJSON (Array a) = ???
我尝试使用Lens销毁数据点记录,但它无法编译:

case a ^.. values . _Integer of -}
  [x,y] -> DataPoint <$> x <*> y
  _     -> mzero
有更好的方法吗?


有没有人有将值数组解析为更详细结构的示例?这里的技巧是从JSON数据点获得正确的
实例,这需要一点匹配,但不是太糟糕。我想出了

instance FromJSON DataPoint where
    parseJSON (Array v)
        | V.length v == 2 = do
            x <- parseJSON $ v V.! 0
            y <- parseJSON $ v V.! 1
            return $ DataPoint x y
        | otherwise = mzero
    parseJSON _ = mzero
如果数据在任何地方格式不正确,这同样会彻底失败。要测试:

> decode "{\"series\": [[1, 2], [3, 4]]}" :: Maybe Series
Just (Series [DataPoint 1 2, DataPoint 3 4])
> decode "{\"series\": [[1, 2], [3, {}]]}" :: Maybe Series
Nothing
所以它看起来是有效的


EDIT:正如@maxtaldykin所指出的,您可以利用
FromJSON a=>FromJSON[a]
实例

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

instance FromJSON Series where
    parseJSON (Object o) = do
        pts <- o .: "series"
        fmap Series $ parseJSON pts
    parseJSON _ = mzero
来自JSON数据点的实例,其中
parseJSON obj=do

[x,y]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
{-#语言LambdaCase}
导入数据.Aeson
数据系列=系列[数据点]
数据点=数据点整数
实例FromJSON数据点,其中
parseJSON jsn=do
[x,y](o.:“系列”)>>=fmap系列。parseJSON
x->fail$“意外json:++show x

我不久前为其他人写了一篇文章,这可能会给你一个好的开始。谢谢Bheklillr,但我遇到的问题不是Aeson的解析(对象解析很简单),而是将数组分解为更具语义的数据类型。数组具有
[X,Y]
,其中它们是两个不同的语义,仅由索引表示。我想把它解析成一个真正的数据类型
DataPoint Int
,这样我可以将类型和名称细化到它应该是什么意思。我必须承认我更喜欢这个答案,我甚至不认为列表可能已经有了一个实例。我也很惊讶地看到了它。感谢您早些时候的快速回答。让我克服了障碍,我最终使用了你的答案和@max taldykin的答案。
instance FromJSON DataPoint where
    parseJSON obj = do
        [x, y] <- parseJSON obj
        return $ DataPoint x y

instance FromJSON Series where
    parseJSON (Object o) = do
        pts <- o .: "series"
        fmap Series $ parseJSON pts
    parseJSON _ = mzero
{-# 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