Report a paste

Please put a quick comment for the admin.

If it looks like spam, the admin will mark it as spam so that the spam filter picks it up in the future.

If the paste contains something private or offensive, it'll probably just be deleted.

No title

{-# LANGUAGE RecordWildCards #-}

module Test where

import           Control.Applicative        ((<|>))
import           Data.Aeson
import           Data.Aeson.Types
import qualified Data.ByteString.Lazy       as LB
import qualified Data.ByteString.Lazy.Char8 as C
import qualified Data.HashMap.Lazy          as HM
import           Data.Monoid                ((<>))
import           Data.Text                  (pack)
import           GHC.Generics               (Generic)
import           Prelude

data Document = Document
  { count  :: Int
  , events :: [Event]
  } deriving (Show)

data Event = Event
  { sequence :: Int
  , entry    :: Entry
  } deriving (Show)

data Entry
  = Content String
  | Answer String String
  deriving (Show)

instance FromJSON Document where
  parseJSON =
    withObject "The document" $ \o -> do
      count <- o .: "count"
      events <- extractKey "events" =<< extractEmbedded o
      return Document {..}

instance FromJSON Event where
    parseJSON = withObject "A event" $ \o -> do
      sequence <- o .: "sequence"
      entry <- extractEntry =<< extractEmbedded o
      return Event {..}

instance FromJSON Entry where
  parseJSON v = parseContent v <|> parseAnswer v

    where
      parseContent :: Value -> Parser Entry
      parseContent = withObject "An entry of type content" $ \o -> do
        content <- o .: "content"
        return $ Content content

      parseAnswer :: Value -> Parser Entry
      parseAnswer = withObject "An entry of type answer" $ \o -> do
        answer <- o .: "answer"
        question <- extractKey "question" =<< extractEmbedded o
        return $ Answer answer question

extractEmbedded :: FromJSON a => Object -> Parser a
extractEmbedded = extractKey "_embedded"

extractEntry :: FromJSON a => Object -> Parser a
extractEntry = extractKey "entry"

extractKey :: FromJSON a => String -> Object -> Parser a
extractKey k o = maybe (fail $ "key " <> show k <> " missing") parseJSON (HM.lookup (pack k) o)

json_data :: IO LB.ByteString
json_data = C.readFile "./src/data.json"

main = do
    c <- json_data
    let v = eitherDecode c :: Either String Document
    putStrLn . show $ v