Разбор вложенных массивов в Aeson - PullRequest
4 голосов
/ 04 апреля 2020

Я изо всех сил пытаюсь разобрать нижеследующее JSON с помощью библиотеки Aeson.
Меня интересует только получение файла1, но мне кажется, я не могу им управлять.
У кого-нибудь есть предложения?

JSON

{"files":[["file1.wav",["file2.jpg","file3.jpg"]]]}

Мой код

data File = File Text deriving (Show, Generic, ToJSON)

instance FromJSON File where
  parseJSON jsn = do
    arrays <- parseJSON jsn
    let x = arrays !! 0 !! 0
    return $ File x

Сообщение об ошибке

"Error in $.files[0][1]: parsing Text failed, expected String, but encountered Array"

1 Ответ

2 голосов
/ 04 апреля 2020

Проблема в использовании parseJSON для разбора jsn в однородный список . Но "file1.wav" - это строка, а ["file2.jpg", "file3.jpg"] - это не строка.

Простое решение состоит в прямом сопоставлении с шаблоном на json, то есть Value, который может содержат гетерогенный Array (несмотря на название, на самом деле это синоним Vector из библиотеки vector ).

{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import qualified Data.Vector as V
import Data.Text (Text)

newtype File = File Text deriving Show

instance FromJSON File where
  parseJSON json = do
    Array arr <- pure json
    Just (Array arr0) <- pure (arr V.!? 0)
    Just (String txt) <- pure (arr0 V.!? 0)
    pure (File txt)

main :: IO ()
main = print (decode' "[[\"file1\", [\"file2\", \"file3\"]]]" :: Maybe File)

((!?) является безопасным оператором индексации. )

...